简体   繁体   中英

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

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");
    }

}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM