简体   繁体   中英

wake up waiting threads

this class works with an executor. the thing is that at some point i want to shut it down, but even if i'm changing the terminateRequested to "true" it wont help those threads stuck waiting in "takeTask" because the vector tasks at that point is always empty. i need them somehow to get to "e.shutDown()" line in run()

public class RunnableStudent implements Runnable{

public void run() {

    while(!terminateRequested){

        this.takeTask();
        this.giveSolution();

    }


    e.shutdown();

}


private synchronized void takeTask(){


          while(tasks.isEmpty()){
               try {

                 this.wait();
              } catch (InterruptedException e) {

                 e.printStackTrace();
              }
          }

         DoSomeWork();
}

public synchronized void shutDown(){


    terminateRequested = true;
    this.notifyAll();

}

You will need to break out of your while tasks.isEmpty()){ loop and out of your while(!terminateRequested){ loop

so I suggest that when you do

} catch (InterruptedException e) {
     e.printStackTrace();
}

you change it to

} catch (InterruptedException e) {
     terminateRequested = true;
     return;
}

As I can not see your giveSolution method I can not tell you have to change it.

Alternatively you could through the InterruptedException from the takeTask method.

Since you're using executor service you can call it's shutdownNow method that is going to actively shut down threads without waiting.

Combining Object.wait and Object.notify with java.util.concurrent smells as per Is using Object.wait and Object.notify directly a code smell?

You need break the loop of while(tasks.isEmpty()) so change the code like this:

public class RunnableStudent implements Runnable{

 private Thread thread;
 public void run() {

    thread = Thread.currentThread();
    while(!terminateRequested){

        this.takeTask();
        this.giveSolution();

   }


   e.shutdown();

 }

 private synchronized void takeTask(){


      while(tasks.isEmpty()){
           try {

             this.wait();
          } catch (InterruptedException e) {
             break;
          }
      }

     DoSomeWork();
}

public synchronized void shutDown(){

     terminateRequested = true;
     thread.interupt();

}

First, if you are having three different RunnableStudent instance ( each instance per thread) and assumed the tasks and terminateRequested are local variables , you dont need to syncronized .becuase there is nothing you are sharing between threads.

Second , if you are using executors , you can use thread pool , that case you dont need to do wait and notify yourself , once the work is completed all the threads ( n number of threads configured while pool iniitalize) in pool will wait for next request ( through executors.submit/execute) . And you can use shutdown / shutdownNow at any given point based on your condition.

Finaly to answer your question, just change the while loop to if conditon in taketask(). All your problems will resolve . because your waiting logic will still holds good with main while loop in run method.

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