线程不会在java中的notifyAll之后打印所有内容

时间:2014-10-07 19:27:05

标签: java multithreading wait synchronized notify

class Lock implements Runnable{
  int i=0;
  public synchronized void run(){
    for(i=0;i<10;i++){
        if(Thread.currentThread().getName().equals("t1") && i == 5)
         {try { this.wait();} catch(InterruptedException ie){}}
        System.out.print(Thread.currentThread().getName()+" ");
        if(Thread.currentThread().getName().equals("t3") && i == 9)
         this.notifyAll();
  }
 }
}
public class ThreadLock {
 public static void main(String[] args){   
  Lock l = new Lock();
  Thread t1 = new Thread(l);
  Thread t2 = new Thread(l);
  Thread t3 = new Thread(l);
  t1.setName("t1");
  t2.setName("t2");
  t3.setName("t3");
  t1.start();
  t2.start();
  t3.start();
 }
}

输出是: t1 t1 t1 t1 t1 t3 t3 t3 t3 t3 t3 t3 t3 t3 t3 t1 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2

调用notifyAll方法后,

t1不会全部打印10次。 我跑了很多次但是每次打印t1只打了6次。 为什么t1不打印10次? 请尽快回复

4 个答案:

答案 0 :(得分:2)

i是一个实例变量。它由所有线程共享。它应该是一个局部变量。

当第一个线程被唤醒时,它会重新获取锁定,打印其名称,递增i,并在i < 10时重新评估。但由于其他线程已将i设置为10,因此循环停止。

答案 1 :(得分:1)

问题是你在线程之间共享相同的索引i,所以当线程t3存在且t1被唤醒时,索引i将是10并且线程中的for循环t1将退出。

答案 2 :(得分:0)

在启动每个线程后尝试在每个线程上调用.join()以确保每个线程在程序退出之前完成?

答案 3 :(得分:0)

虽然JB Nizet已经给出了正确答案,但您可能想知道为什么这只会影响t1: 当调用run方法(已同步)时,每个线程都重置i

但是当你返回t1的执行时 - 它不会重置i,因为线程已经启动了for - 循环。

   i | output
   0 | t1 (FIRST iteration of t1 -> Setting i=0)
   1 | t1
   2 | t1
   3 | t1
   4 | t1
   5 | t1
   0 | t3 (FIRST iteration of t3 -> Setting i = 0)
   1 | t3
   2 | t3
   3 | t3
   4 | t3
   5 | t3
   6 | t3
   7 | t3
   8 | t3
   9 | t3
   0 | t2 (FIRST iteration of t2 -> Setting i = 0)
   1 | t2
   2 | t2
   3 | t2
   4 | t2
   5 | t2
   6 | t2
   7 | t2
   8 | t2
   9 | t2
   9 | t1 (t1 restored, but i=9 now. One more output, program done)

注意:这至少是您描述的输出正在发生的事情。我认为也可能是t2在t3之前执行,导致输出不同。