简体   繁体   中英

How to cancel all the thread/ threads in ExcecutorService?

I've written following multi thread program. I want to cancel the all the thread if one of the thread sends back false as return. However though I'm canceling the thread by canceling individual task. Its not working. What changes I need to make inorder to cancel the thread?

I've written following multi thread program. I want to cancel the all the thread if one of the thread sends back false as return. However though I'm canceling the thread by canceling individual task. Its not working. What changes I need to make inorder to cancel the thread?

import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.Callable;

public class BeamWorkerThread implements Callable<Boolean> {


  private List<BeamData> beamData;
  private String threadId;



 public BeamScallopingWorkerThread(
    List<BeamData> beamData, String threadId) {
   super();
   this.beamData = beamData;
   this.threadId = threadId;
  }





 @Override
  public Boolean call() throws Exception {

  Boolean result = true;

  DataValidator validator = new DataValidator();
   Iterator<BeamScallopingData> it = beamData.iterator();

  BeamData data = null;
  while(it.hasNext()){

   data = it.next();

   if(!validator.validateDensity(data.getBin_ll_lat(), data.getBin_ll_lon(), data.getBin_ur_lat(), data.getBin_ur_lon())){
     result = false;
     break;
    }
   }
   return result;
  }

}









   ExecutorService threadPool = Executors.newFixedThreadPool(100);
        List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();

        long count = 0;
         final long RowLimt = 10000;
         long threadCount = 1;

        while ((beamData = csvReader.read(
           BeamData.class, headers1, processors)) != null) {

         if (count == 0) {
           beamDataList = new ArrayList<BeamData>();
          }

         beamDataList.add(beamData);
          count++;
          if (count == RowLimt) {
           results.add(threadPool
             .submit(new BeamWorkerThread(
               beamDataList, "thread:"
                 + (threadCount++))));
           count = 0;
          }
         }

        results.add(threadPool.submit(new BeamWorkerThread(
           beamDataList, "thread:" + (threadCount++))));
         System.out.println("Number of threads" + threadCount);
         for (Future<Boolean> fs : results)
          try {


           if(fs.get() == false){
            System.out.println("Thread is false");
            for(Future<Boolean> fs1 : results){
             fs1.cancel(true);
            }
           }
          } catch(CancellationException e){

         } catch (InterruptedException e) {

         } catch (ExecutionException e) {

         } finally {
           threadPool.shutdownNow();
          }

       }

My comments

Thanks all for your input I'm overwhelmed by the response. I do know that, well implemented thread takes an app to highs and mean time it a bad implementation brings the app to knees. I agree I'm having fancy idea but I don't have other option. I've a 10 million plus record hence I will have memory constraint and time constraint. I need to tackle both. Hence rather than swallowing whole data I'm breaking it into chunks and also if one data is invalid i don't want to waste time in processing remaining million data. I find @Mark Peters suggestion is an option. Made the changes accordingly I mean added flag to interrupt the task and I'm pretty confused how the future list works. what I understand is that looping through each field of future list starts once all the thread returns its value. In that case, there is no way to cancel all the task in half way from main list. I need to pass on the reference of object to each thread. and if one thread finds invalid data using the thread refernce call the cancel mathod of each thread to set the interrupt flag.

while(it.hasNext() && !cancelled) {
         if(!validate){
               // loop through each thread reference and call Cancel method
         }
      }

Whatever attempt you make to cancel all the remaining tasks, it will fail if your code is not carefully written to be interruptible . What that exactly entails is beyond just one StackOverflow answer. Some guidelines:

  • do not swallow InterruptedException . Make its occurrence break the task;
  • if your code does not spend much time within interruptible methods, you must insert explicit Thread.interrupted() checks and react appropriately.

Writing interruptible code is in general not beginner's stuff, so take care.

Cancelling the Future will not interrupt running code. It primarily serves to prevent the task from being run in the first place.

While you can provide a true as a parameter, which will interrupt the thread running the task, that only has an effect if the thread is blocked in code that throws an InterruptedException . Other than that, nothing implicitly checks the interrupted status of the thread.

In your case, there is no blocking; it's busy work that is taking time. One option would be to have a volatile boolean that you check at each stage of your loop:

public class BeamWorkerThread implements Callable<Boolean> {

   private volatile boolean cancelled = false;
   @Override
   public Boolean call() throws Exception {
      //...
      while(it.hasNext() && !cancelled) {
         //...
      }
   }

   public void cancel() {
       cancelled = true;
   }
}

Then you would keep references to your BeamWorkerThread objects and call cancel() on it to preempt its execution.

Why don't I like interrupts?

Marko mentioned that the cancelled flag above is essentially reinventing Thread.interrupted() . It's a valid criticism. Here's why I prefer not to use interrupts in this scenario.

1. It's dependent on certain threading configurations.

If your task represents a cancellable piece of code that can be submitted to an executor, or called directly, using Thread.interrupt() to cancel execution in the general case assumes that the code receiving the interrupt will be the code that should know how to cleanly cancel the task.

That might be true in this case, but we only know so because we know how both the cancel and the task work internally. But imagine we had something like this:

  • Task does piece of work
  • Listeners are notified on-thread for that first piece of work
    • First listener decides to cancel the task using Thread.interrupt()
    • Second listener does some interruptible piece of work, and is interrupted. It logs but otherwise ignores the interrupt.
  • Task does not receive interrupt, and task is not cancelled.

In other words, I feel that interrupt() is too global of a mechanism. Like any shared global state, it makes assumptions about all of the actors. That's what I mean by saying that using interrupt() exposes/couples to details about the run context. By encapsulating it in a cancel() method applicable only for that task instance, you eliminate that global state.

2. It's not always an option.

The classic example here is an InputStream . If you have a task that blocks on reading from an InputStream , interrupt() will do nothing to unblock it. The only way to unblock it is to manually close the stream, and that's something best done in a cancel() method for the task itself. Having one way to cancel a task (eg Cancellable ), regardless of its implementation, seems ideal to me.

Use the ExecutorService.shutdownNow() method. It will stop the executor from accepting more submissions and returns with the Future objects of the ongoing tasks that you can call cancel(true) on to interrupt the execution. Of course, you will have to discard this executor as it cannot be restarted.

The cancel() method may not terminate the execution immediately if the Thread is not waiting on a monitor (not blocked interruptibly), and also if you swallow the InterruptedException that will be raised in this case.

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