Java 如何取消ExcecutorService中的所有线程?

Java 如何取消ExcecutorService中的所有线程?,java,Java,我编写了以下多线程程序。我想取消所有的线程,如果其中一个线程返回false作为返回。然而,尽管我通过取消单个任务来取消线程。它不起作用。为了取消线程,我需要做哪些更改 import java.util.Iterator; import java.util.List; import java.util.concurrent.Callable; public class BeamWorkerThread implements Callable<Boolean> { priv

我编写了以下多线程程序。我想取消所有的线程,如果其中一个线程返回false作为返回。然而,尽管我通过取消单个任务来取消线程。它不起作用。为了取消线程,我需要做哪些更改

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

       }
我编写了以下多线程程序。我想取消所有的线程,如果其中一个线程返回false作为返回。然而,尽管我通过取消单个任务来取消线程。它不起作用。为了取消线程,我需要做哪些更改

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

       }
使用ExecutorService.shutdownNow方法。它将阻止执行者接受更多提交,并返回正在进行的任务的未来对象,您可以调用canceltrue来中断执行。当然,您必须放弃此执行器,因为它无法重新启动

如果线程没有在未被中断的监视器上等待,并且如果您接受了在这种情况下将引发的InterruptedException,则cancel方法可能不会立即终止执行。

使用ExecutorService.Shutdownow方法。它将阻止执行者接受更多提交,并返回正在进行的任务的未来对象,您可以调用canceltrue来中断执行。当然,您必须放弃此执行器,因为它无法重新启动


如果线程未在未被中断的监视器上等待,并且如果您接受了在这种情况下将引发的InterruptedException,则cancel方法可能不会立即终止执行。

无论您尝试取消所有剩余任务,如果您的代码没有被仔细地编写为可中断的,那么它将失败。这就意味着不仅仅是一个答案。一些准则:

不要吞下中断异常。使其发生中断任务; 如果代码在可中断方法中花费的时间不多,则必须插入显式的Thread.interrupted检查并做出适当的反应。
编写可中断代码通常不是初学者的事,所以要当心。

无论您试图取消所有剩余的任务,如果您的代码没有认真编写为可中断的,它都将失败。这就意味着不仅仅是一个答案。一些准则:

不要吞下中断异常。使其发生中断任务; 如果代码在可中断方法中花费的时间不多,则必须插入显式的Thread.interrupted检查并做出适当的反应。 编写可中断代码通常不是初学者的事情,所以要小心。

取消以后的操作不会中断正在运行的代码。它主要用于防止任务首先运行

虽然您可以提供一个true作为参数,该参数将中断运行任务的线程,但只有当线程在抛出InterruptedException的代码中被阻塞时,该参数才有效。除此之外,没有任何内容隐式检查线程的中断状态

在您的情况下,没有阻塞;忙碌的工作需要时间。一个选项是在循环的每个阶段检查一个易失性布尔值:

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;
   }
}
然后,您将保留对BeamWorkerThread对象的引用,并对其调用cancel以抢占其执行

为什么我不喜欢打断别人? Marko提到,上面的取消标志实质上是重新创建Thread.interrupted。这是一个合理的批评。这就是为什么我不喜欢在这个场景中使用中断

一,。这取决于某些线程配置

如果您的任务表示可以提交给执行器或直接调用的可取消代码段,则在一般情况下,使用Thread.interrupt取消执行假定接收中断的代码将是应该知道如何干净地取消任务的代码

在本例中可能是这样,但我们之所以知道这一点,是因为我们知道取消和任务在内部是如何工作的。但是想象一下我们有这样的事情:

任务完成一项工作 侦听器会在线程上收到第一件工作的通知 第一个侦听器决定使用Thread.interrupt取消任务 第二个听众做了一些可打断的工作,被打断了。它会记录日志,但会忽略中断。 任务未收到中断,且任务未取消。 换句话说,我觉得中断是一种过于全局的机制。与任何共享的全球国家一样,它对所有参与者都做出假设。这就是我所说的使用中断暴露/耦合运行上下文的细节的意思。通过将其封装在仅适用于该任务实例的cancel方法中,可以消除该全局状态

二,。这并不总是一种选择

这里的经典示例是InputStream。如果您有一个阻止读取输入的任务 流,中断将无法解除阻止它。解除阻止它的唯一方法是手动关闭流,这最好是在任务本身的cancel方法中完成。对于我来说,有一种方法可以取消一项任务,例如可取消,不管它的实现如何,都是理想的选择。

取消未来的任务不会中断正在运行的代码。它主要用于防止任务首先运行

虽然您可以提供一个true作为参数,该参数将中断运行任务的线程,但只有当线程在抛出InterruptedException的代码中被阻塞时,该参数才有效。除此之外,没有任何内容隐式检查线程的中断状态

在您的情况下,没有阻塞;忙碌的工作需要时间。一个选项是在循环的每个阶段检查一个易失性布尔值:

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;
   }
}
然后,您将保留对BeamWorkerThread对象的引用,并对其调用cancel以抢占其执行

为什么我不喜欢打断别人? Marko提到,上面的取消标志实质上是重新创建Thread.interrupted。这是一个合理的批评。这就是为什么我不喜欢在这个场景中使用中断

一,。这取决于某些线程配置

如果您的任务表示可以提交给执行器或直接调用的可取消代码段,则在一般情况下,使用Thread.interrupt取消执行假定接收中断的代码将是应该知道如何干净地取消任务的代码

在本例中可能是这样,但我们之所以知道这一点,是因为我们知道取消和任务在内部是如何工作的。但是想象一下我们有这样的事情:

任务完成一项工作 侦听器会在线程上收到第一件工作的通知 第一个侦听器决定使用Thread.interrupt取消任务 第二个听众做了一些可打断的工作,被打断了。它会记录日志,但会忽略中断。 任务未收到中断,且任务未取消。 换句话说,我觉得中断是一种过于全局的机制。与任何共享的全球国家一样,它对所有参与者都做出假设。这就是我所说的使用中断暴露/耦合运行上下文的细节的意思。通过将其封装在仅适用于该任务实例的cancel方法中,可以消除该全局状态

二,。这并不总是一种选择


这里的经典示例是InputStream。若您有一个阻止从InputStream读取的任务,中断将不会解除阻止它。解除阻止它的唯一方法是手动关闭流,这最好是在任务本身的cancel方法中完成。在我看来,有一种方法可以取消一项任务,例如可取消,而不管它的实现如何,这似乎是理想的选择。

你为什么要在问题中加入所有这些不相关的代码?看看Executor服务API,看看Executor服务javadoc,我认为您需要使用我使用过的shutdownNow方法。还是没用。验证100万条记录需要1.5秒。当我返回错误时,说是1000太阳记录。它仍然需要1.5秒。我预计它将少于500微秒。我建议您考虑一下您的设计,如果它是如此高性能的话。不要以秒为先来思考,而是要试着理解如何以及何时可以中断执行,以及如何中断执行。试着用Java工具来实现,不要试图想出一个新的花哨的想法。@SRT_KP我想你的意思是500毫秒,而不是实际上的500毫秒0.5毫秒。你为什么要把这些无关的代码放在你的问题中?看看Executor服务API,看看Executor服务javadoc,我认为您需要使用我使用过的shutdownNow方法。还是没用。验证100万条记录需要1.5秒。当我返回错误时,说是1000太阳记录。它仍然需要1.5秒。我预计它将少于500微秒。我建议您考虑一下您的设计,如果它是如此高性能的话。不要以秒为先来思考,而是要试着理解如何以及何时可以中断执行,以及如何中断执行。试着用Java工具来实现,不要试图想出一个新的花哨的想法。@SRT_KP我想你的意思是500毫秒,而不是实际上500微秒0.5毫秒。除了Java自己的中断机制之外,你不应该推荐一种中断机制,它响应canceltrue,还有许多其他好处。我同意@MarkoTopolnik。中断已经相当困难,创建另一个实现是无用的。我们可以在教程中看到这些解决方案,但不值得这么做。学习如何用Java的方式来做,你在任何地方都可以。没有任何情况下你需要实现这样的东西。当线程等待监视器时,会抛出InterruptedException,当它在循环中运行时,可以检查Thread.interrupted标志。事实上根本没有这种情况
当你不得不创造这些技巧时。是的,但是你说第一个听众会引起中断。然后控制返回到主侦听器通知循环,该循环有机会中止。除此之外,关于外星代码的争论是绝对有效的,不久前我甚至用这一点写了一个答案。@Marko:啊,这一点很好,我假设这与执行者想要重用线程时会做的事情类似:毕竟,你可以有一个等价的场景,你可以中断地取消一个任务,但该任务不会清除中断状态。您当然不希望下一个使用该线程的任务因为运气不好而立即中断。但是添加另一个间接层次,场景仍然存在:-。除了Java自己的中断机制之外,您不应该推荐其他中断机制,它响应canceltrue,还有许多其他好处。我同意@MarkoTopolnik。中断已经相当困难,创建另一个实现是无用的。我们可以在教程中看到这些解决方案,但不值得这么做。学习如何用Java的方式来做,你在任何地方都可以。没有任何情况下你需要实现这样的东西。当线程等待监视器时,会抛出InterruptedException,当它在循环中运行时,可以检查Thread.interrupted标志。实际上,没有任何情况下你必须创造出这样的技巧。是的,但是你说第一个听众引起了中断。然后控制返回到主侦听器通知循环,该循环有机会中止。除此之外,关于外星代码的争论是绝对有效的,不久前我甚至用这一点写了一个答案。@Marko:啊,这一点很好,我假设这与执行者想要重用线程时会做的事情类似:毕竟,你可以有一个等价的场景,你可以中断地取消一个任务,但该任务不会清除中断状态。您当然不希望下一个使用该线程的任务因为运气不好而立即中断。但再加上另一个间接层次,情况仍然存在:-。