黑马程序员技术交流社区

标题: 【问题篇】空中网线程题--第三题 [打印本页]

作者: yi岁⑨很乖❤    时间: 2015-1-24 11:34
标题: 【问题篇】空中网线程题--第三题
本帖最后由 yi岁⑨很乖❤ 于 2015-4-13 21:04 编辑

package cn.itcast.day04.test;

import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;

/*第三题:现有程序同时启动了4个线程去调用TestDo2.doSome(key, value)方法,由于TestDo2.doSome(key, value)方法内的代码是先暂停1秒,
然后再输出以秒为单位的当前时间值,所以,会打印出4个相同的时间值,如下所示:
4:4:1258199615
1:1:1258199615
3:3:1258199615
1:2:1258199615
请修改代码,如果有几个线程调用TestDo2.doSome(key, value)方法时,传递进去的key相等(equals比较为true),
则这几个线程应互斥排队输出结果,即当有两个线程的key都是"1"时,它们中的一个要比另外其他线程晚1秒输出结果,如下所示:
4:4:1258199615
1:1:1258199615
3:3:1258199615
1:2:1258199616
总之,当每个线程中指定的key相等时,这些相等key的线程应每隔一秒依次输出时间值(要用互斥),如果key不同,
则并行执行(相互之间不互斥)。原始代码如下:*/



//不能改动此Test3类        
public class Test3 extends Thread {

        private TestDo3 testDo;
        private String key;
        private String value;

        public Test3(String key, String key2, String value) {
                this.testDo = TestDo3.getInstance();
                /*
                 * 常量"1"和"1"是同一个对象,下面这行代码就是要用"1"+""的方式产生新的对象,
                 * 以实现内容没有改变,仍然相等(都还为"1"),但对象却不再是同一个的效果
                 */
                this.key = key + key2;
                this.value = value;
        }

        public static void main(String[] args) throws InterruptedException {
                Test3 a = new Test3("1", "", "1");
                Test3 b = new Test3("1", "", "2");
                Test3 c = new Test3("3", "", "3");
                Test3 d = new Test3("4", "", "4");
                System.out.println("begin:" + (System.currentTimeMillis() / 1000));
                a.start();
                b.start();
                c.start();
                d.start();

        }

        public void run() {
                testDo.doSome(key, value);
        }
}

class TestDo3 {

        private TestDo3() {}

        private static TestDo3 _instance = new TestDo3();

        public static TestDo3 getInstance() {
                return _instance;
        }

        /*public void doSome(Object key, String value) {

                // 以大括号内的是需要局部同步的代码,不能改动!
                {
                        try {
                                Thread.sleep(1000);
                                System.out.println(key + ":" + value + ":" + (System.currentTimeMillis() / 1000));
                        } catch (InterruptedException e){
                                e.printStackTrace();
                        }
                }
        }*/
        
//        方法一:
        /*public void doSome(Object key, String value) {
                Integer o = Integer.parseInt((String)key);
                synchronized(o)
                // 以大括号内的是需要局部同步的代码,不能改动!
                {
                        try {
                                Thread.sleep(1000);
                                System.out.println(key + ":" + value + ":" + (System.currentTimeMillis() / 1000));
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                }
        }*/

//        方法二:
        Collection<Object> lists = new CopyOnWriteArrayList<Object>();
        public void doSome(Object key, String value) {
                Object o = key;
                if(!lists.contains(o))
                {
                        lists.add(o);
                }
                else
                {
                        for (Object list : lists) {
                                if(list.equals(o))
                                {
                                        o = list;
                                }
                        }
//                        for (Iterator<Object> list = lists.iterator(); list.hasNext();) {
//                                Object oo = list.next();
//                                if(oo.equals(o))
//                                {
//                                        o = oo;
//                                }
//                                
//                        }
                }
                        
                synchronized(o)
                // 以大括号内的是需要局部同步的代码,不能改动!
                {
                        try {
                                Thread.sleep(1000);
                                System.out.println(key + ":" + value + ":" + (System.currentTimeMillis() / 1000));
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                }
        }
}

方法二 是张孝祥老师的完整版解答,但是超多次运行后,抓取到的一个错误输出:
begin:1421946350
1:2:1421946351
4:4:1421946351
1:1:1421946351
3:3:1421946351
请大家帮我来解答一下,谢谢啦~~~






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2