如果其他线程正在等待,线程是否隐式调用notifyAll()?

时间:2014-04-21 20:13:32

标签: java multithreading notify

我认为我应该说的第一件事是我不是在寻找解决方案,这是hwk,但是它运行正常,对我来说有什么帮助可以澄清......

我们刚刚在面向对象的编程类中引入了线程,并收到了一个我完成的任务。在我的代码中,我从不调用notifyAll(),但似乎在退出run()之前隐式调用它。我的另一位同学也有同样的问题。我在某个地方读到一个正在等待另一个线程的线程被通知(隐式notifyAll()?)当它正在等待的线程死亡/退出run方法时。这是我的代码(runnable,以及它运行的主要部分)

如果我删除了等待,并用Throwable替换InterruptedException,则代码运行,但不正确,线程在其休眠时间之后出现,然后打印终止消息并按照它们出现的顺序消亡。

我无法发布图片,所以我尽力描述它是如何工作的: 每个线程在分配的时间内休眠,并保存一个Thread数组,该数组保存对必须等待的线程的引用

ex:T1到达2秒取决于T2,T3     T2到达4秒取决于没有人     T3到达6秒取决于没有人 所以... T1到达并且必须等待T2和T3才能终止,T2和T3可以立即终止..

这是到达时间和他们依赖的人:

T1 4秒,没有人 T2 6秒,没有人 T3 7秒,没有人 T4 2秒,T1,T2 T5 3秒,T3 T6 1秒,T3,T4 T7 8秒,T4 T8 5秒,T6

对于可怕的长解释感到抱歉,我不是在寻找解决方案,代码运行正常,我需要澄清一下如果调用wait并且从不调用notify如何运行?

public class TScheduler {




    public static void main(String[] args) {




    long originTime = System.currentTimeMillis();

    // Long.parse.long(args[0]) * 1000
    DepThread t1 = new DepThread(originTime , 4000 , new Thread[]{});
    Thread T1 = new Thread(t1);
    T1.setName("T1");
    // Long.parse.long(args[1]) * 1000
    DepThread t2 = new DepThread(originTime , 6000 , new Thread[]{});
    Thread T2 = new Thread(t2);
    T2.setName("T2");

    DepThread t3 = new DepThread(originTime , 7000 , new Thread[]{});
    Thread T3 = new Thread(t3);
    T3.setName("T3");

    DepThread t4 = new DepThread(originTime , 2000 , new Thread[]{T1,T2});
    Thread T4 = new Thread(t4);
    T4.setName("T4");

    DepThread t5 = new DepThread(originTime , 3000 , new Thread[]{T3});
    Thread T5 = new Thread(t5);
    T5.setName("T5");

    DepThread t6 = new DepThread(originTime , 1000 , new Thread[]{T3,T4});
    Thread T6 = new Thread(t6);
    T6.setName("T6");

    DepThread t7 = new DepThread(originTime , 8000 , new Thread[]{T4});
    Thread T7 = new Thread(t7);
    T7.setName("T7");

    DepThread t8 = new DepThread(originTime ,5000 , new Thread[]{T6});
    Thread T8 = new Thread(t8);
    T8.setName("T8");

    DepThread t9 = new DepThread(originTime , 500 , new Thread[]{T7});
    Thread T9 = new Thread(t9);
    T9.setName("T9");




    T1.start();
    T2.start();
    T3.start();
    T4.start();
    T5.start();
    T6.start();
    T7.start();
    T8.start();
    T9.start();






    }

}




public class DepThread implements Runnable {

    long sleepTime;
    Thread[] depThrdArray;
    public boolean done = false ;
    long baseTime ;

    public DepThread( long baseTime , long arrivalTime ,  Thread[] depThrdArray ){
    //super();
    this.baseTime = baseTime;
    this.sleepTime = arrivalTime;
    this.depThrdArray = depThrdArray;
    this.done = false;
    }

    @Override
    public void run() { 
    try {
        Thread.sleep(sleepTime);
        System.out.println( Thread.currentThread().getName() + " arrived at " + (System.currentTimeMillis() - baseTime));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    for ( int i = 0 ; i < depThrdArray.length ; i ++){
        if ( depThrdArray[i].isAlive()){
        synchronized(depThrdArray[i]){
            try {
            depThrdArray[i].wait();
            System.out.println(Thread.currentThread().getName() + " waiting on " + depThrdArray[i].getName() 
                + " time " + (System.currentTimeMillis() - this.baseTime));
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
        }
        }

    }

    this.done = true;
    //synchronized (this){
    //    notifyAll();
    //}
    System.out.println(Thread.currentThread().getName() + "  at time " + ( System.currentTimeMillis() -  baseTime) + " terminating");
    }

}

1 个答案:

答案 0 :(得分:3)

在终止时线程调用notifyAll以支持join功能。这在Thread#join的Javadoc中有记录:

  

此实现使用以this.wait为条件的this.isAlive次调用循环。当线程终止时,将调用this.notifyAll方法。建议应用程序不要在wait个实例上使用notifynotifyAllThread

基本上有两个结论:

  • 如果您想等到线程终止,请使用join
  • 如果您想使用wait,请不要将Thread实例用作监视器。