Does a thread implicitly call notifyAll() , if other Threads are waiting on it?

蹲街弑〆低调 提交于 2019-11-30 09:40:30

问题


First thing i think i should say is that i am not looking for a solution , this is hwk , but it runs correctly , what would help me greatly is come clarification..

We were just introduce to threads in my object oriented programing class , and received an assignment , which I completed. In my code I never call notifyAll() , but it seems as though it is called implicitly before exiting the run(). Another classmate of mine had the same question. I read somewhere that a Thread that is waiting on another Thread is notified ( implicit notifyAll() ?) when the thread it is waiting on dies/exits the run method. here is my code ( the runnable , and the main where it all runs)

if I remove the wait, and the replace the InterruptedException with Throwable , the code runs , but not correctly , the threads appear after their sleep time then print the termination message and die in the order they appear.

I couldnt post a pic so ill do my best to describe how it works: each thread sleeps for the alloted time and holds a Thread array , which holds references to threads it must wait for

ex: T1 arrives at 2 seconds depends T2,T3 T2 arrives at 4 seconds depends on no-one T3 arrives at 6 seconds depends on no-one so... T1 arrives and has to wait for T2 and T3 before it can terminate, T2 and T3 can terminate immediately..

here are the arrival times and who they depend on:

T1 4 sec , no-one T2 6 sec , no-one T3 7 sec , no-one T4 2 sec , T1,T2 T5 3 sec , T3 T6 1 sec , T3,T4 T7 8 sec , T4 T8 5 sec , T6

sorry about the horrendously long explanation , i am not looking for a solution , the code runs properly , i need some clarification on how if wait is called and notify is never called how it runs?

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:


Thread calls notifyAll upon termination in support of the join functionality. This is documented in the Javadoc for Thread#join:

This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

There are essentially two conclusions then:

  • If you want to wait until a Thread terminates, use join.
  • If you want to use wait otherwise, do not use a Thread instance as a monitor.


来源:https://stackoverflow.com/questions/23205200/does-a-thread-implicitly-call-notifyall-if-other-threads-are-waiting-on-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!