解决方案 »

  1.   

    同问,ExecutorService起到阻塞的作用?
      

  2.   

    受到启发,用new Thread的方式试了下,发现没问题;看来是因为 ExecutorService导致的,但它是怎么做到的呢,希望有大拿能给出解答!
      

  3.   

    受到启发,用new Thread的方式试了下,发现没问题;看来是因为 ExecutorService导致的,但它是怎么做到的呢,希望有大拿能给出解答!
    我也用new Thread的方法试了一下,结果跟ExecutorService的一样,应该不是ExecutorService的问题
      

  4.   

    这里并非因为阻塞了,而是因为两个++val执行所需要的时间太小了,而造成了你的一种错觉。
    你在++val中间加上一行try{ Thread.sleep(100); }catch(Exception e){}很快你就会发现最终只有一个线程在跑了,其它9个都会在很短的时间内结束掉。
      

  5.   

    最好先试一下楼主的代码再说话你说了之后,我特意运行了一下,没有发现有阻塞啊。你所说的阻塞是在哪。
    把这句注释掉结果就不一样了
    System.out.println(val); 
      

  6.   

    最好先试一下楼主的代码再说话你说了之后,我特意运行了一下,没有发现有阻塞啊。你所说的阻塞是在哪。
    把这句注释掉结果就不一样了
    System.out.println(val); 
    我还以为你们说的是什么。我第一个回复是没错的。并非是因为println阻塞,而是因为println所消耗的时间远远超过++val的时间,而造成的错觉。只需在两个++中间sleep一个时间段,就能够很轻易的看到效果了。
      

  7.   

    最好先试一下楼主的代码再说话你说了之后,我特意运行了一下,没有发现有阻塞啊。你所说的阻塞是在哪。
    把这句注释掉结果就不一样了
    System.out.println(val); 
    我还以为你们说的是什么。我第一个回复是没错的。并非是因为println阻塞,而是因为println所消耗的时间远远超过++val的时间,而造成的错觉。只需在两个++中间sleep一个时间段,就能够很轻易的看到效果了。可能是跟System.out 获得的流有关。
      

  8.   

    又是一个讨论离题的帖子,查下源代码就知道原因了。public void println(int x) {
    synchronized (this) {
        print(x);
        newLine();
    }
    }
      

  9.   

    其实并没有阻止并发,将程序改成这样
    private static int val = 0;
    private int i = 10; @Override
    public void run() {
    while (i-- > 0) {
    ++val;
    ++val;
    System.out.println(Thread.currentThread().getId() + ":" + val); // 在我电脑上测试,此处添加打印输出似乎防止了并发的产生,为什么?
    if (val % 2 != 0) {
    System.out.println(val + " not event!");
    return;
    }
    }
    }
    得到的结果是
    10:10
    10:68
    10:70
    10:72
    10:74
    10:76
    10:78
    10:8
    10:80
    10:84
    11:116
    11:118
    11:120
    11:122
    11:124
    11:26
    11:28
    11:30
    11:34
    11:8
    12:152
    12:156
    12:168
    12:170
    12:174
    12:178
    12:182
    12:186
    12:190
    12:90
    13:114
    13:126
    13:128
    13:130
    13:132
    13:162
    13:32
    13:36
    13:38
    13:40
    14:22
    14:50
    14:52
    14:54
    14:56
    14:58
    14:60
    14:62
    14:64
    14:66
    15:100
    15:102
    15:104
    15:106
    15:108
    15:110
    15:112
    15:46
    15:96
    15:98
    16:136
    16:138
    16:140
    16:142
    16:144
    16:146
    16:148
    16:150
    16:158
    16:92
    17:154
    17:172
    17:180
    17:188
    17:192
    17:194
    17:196
    17:198
    17:200
    17:82
    8:134
    8:160
    8:164
    8:166
    8:176
    8:184
    8:52
    8:86
    8:90
    8:94
    9:12
    9:14
    9:16
    9:18
    9:20
    9:24
    9:42
    9:46
    9:48
    9:8

    可以看出线程间还是交叉运行的,val++的操作都执行完了,我觉得可能是每个线程都在等待IO的调用,所以获得数都是偶数,这个应该跟线程与IO调用关系有关
      

  10.   

    Hi,我做了个实验,我发现没有打印方法的代码更容易出现奇数退出程序。但并不是说有System的代码不会出现奇数。
    请用调试模式启动System打印的代码,在not event处打上断点。立即会得到断点进入,并且完成线程退出。这可以说明这条语句没有造成妨碍并发,只是使得并发更难发生。至于为什么更难,我也不太清楚。
      

  11.   

    要的就是你的答案!
    out对象加的同步锁与楼主描述的状况并无实际关联。其实并没有阻止并发,将程序改成这样
    private static int val = 0;
    private int i = 10; @Override
    public void run() {
    while (i-- > 0) {
    ++val;
    ++val;
    System.out.println(Thread.currentThread().getId() + ":" + val); // 在我电脑上测试,此处添加打印输出似乎防止了并发的产生,为什么?
    if (val % 2 != 0) {
    System.out.println(val + " not event!");
    return;
    }
    }
    }
    得到的结果是
    10:10
    10:68
    10:70
    10:72
    10:74
    10:76
    10:78
    10:8
    10:80
    10:84
    11:116
    11:118
    11:120
    11:122
    11:124
    11:26
    11:28
    11:30
    11:34
    11:8
    12:152
    12:156
    12:168
    12:170
    12:174
    12:178
    12:182
    12:186
    12:190
    12:90
    13:114
    13:126
    13:128
    13:130
    13:132
    13:162
    13:32
    13:36
    13:38
    13:40
    14:22
    14:50
    14:52
    14:54
    14:56
    14:58
    14:60
    14:62
    14:64
    14:66
    15:100
    15:102
    15:104
    15:106
    15:108
    15:110
    15:112
    15:46
    15:96
    15:98
    16:136
    16:138
    16:140
    16:142
    16:144
    16:146
    16:148
    16:150
    16:158
    16:92
    17:154
    17:172
    17:180
    17:188
    17:192
    17:194
    17:196
    17:198
    17:200
    17:82
    8:134
    8:160
    8:164
    8:166
    8:176
    8:184
    8:52
    8:86
    8:90
    8:94
    9:12
    9:14
    9:16
    9:18
    9:20
    9:24
    9:42
    9:46
    9:48
    9:8

    可以看出线程间还是交叉运行的,val++的操作都执行完了,我觉得可能是每个线程都在等待IO的调用,所以获得数都是偶数,这个应该跟线程与IO调用关系有关我认为13楼说的是对的。
      

  12.   

    其实并没有阻止并发,将程序改成这样
    private static int val = 0;
    private int i = 10; @Override
    public void run() {
    while (i-- > 0) {
    ++val;
    ++val;
    System.out.println(Thread.currentThread().getId() + ":" + val); // 在我电脑上测试,此处添加打印输出似乎防止了并发的产生,为什么?
    if (val % 2 != 0) {
    System.out.println(val + " not event!");
    return;
    }
    }
    }
    得到的结果是9:8

    可以看出线程间还是交叉运行的,val++的操作都执行完了,我觉得可能是每个线程都在等待IO的调用,所以获得数都是偶数,这个应该跟线程与IO调用关系有关能说的更详细点吗?线程与IO调用有什么关系呢?
      

  13.   

    System.out这个获得的都是同一个对象,synchronized (this)用这个锁就能保证异步了,不会同步执行。
    多写点多线程例子,就能很容易理解。
      

  14.   

    System.out这个获得的都是同一个对象,synchronized (this)用这个锁就能保证异步了,不会同步执行。
    多写点多线程例子,就能很容易理解。
    public void run() {
    while (true) {
    ++val;
    ++val;
    // System.out.println(val);
    synchronized (System.out) {
    }
    if (val % 2 != 0) {
    System.out.println(val + " not event!");
    return;
    }
    }
    }
    我可以这么理解吗?还是不行啊!
      

  15.   

    理解是可以这么理解的,但是实际情况还有事情需求考虑。
    synchronized (System.out) {}这里一定要有耗时操作,时间必须超过new10次的时间 EvenCheckerEasy(),因为按你这样写,第一个start走到synchronized (System.out)时,如果有一个EvenCheckerEasy刚刚开始start,第一个判断val % 2 != 0前,正好这个个EvenCheckerEasy刚做一次++val,这个线程还没有开始竞争锁操作,第一个线程正好val变成单数了。
    你可以用这样代码注释下下前后对比。public void run() {
            while (true) {
                ++val;
                ++val;
                synchronized (System.out) {//注释掉这行测试
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }//注释掉这行测试
                if (val % 2 != 0) {
                    System.out.println(val + " not event!");
                    return;
                }
            }
        }
    当原理很明确的时候,出现奇怪现象,你只要逐行看看你的代码,你自己就能想清楚为什么出现这个情况。
      

  16.   

    理解是可以这么理解的,但是实际情况还有事情需求考虑。
    synchronized (System.out) {}这里一定要有耗时操作,时间必须超过new10次的时间 EvenCheckerEasy(),因为按你这样写,第一个start走到synchronized (System.out)时,如果有一个EvenCheckerEasy刚刚开始start,第一个判断val % 2 != 0前,正好这个个EvenCheckerEasy刚做一次++val,这个线程还没有开始竞争锁操作,第一个线程正好val变成单数了。
    你可以用这样代码注释下下前后对比。public void run() {
            while (true) {
                ++val;
                ++val;
                synchronized (System.out) {//注释掉这行测试
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }//注释掉这行测试
                if (val % 2 != 0) {
                    System.out.println(val + " not event!");
                    return;
                }
            }
        }
    当原理很明确的时候,出现奇怪现象,你只要逐行看看你的代码,你自己就能想清楚为什么出现这个情况。good,解释的很清楚!