java 如何立即强制终止 ThreadPoolExecutor 中的所有工作线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12821849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 10:21:17  来源:igfitidea点击:

How to force terminate all workers in ThreadPoolExecutor immediately

javamultithreadingthreadpoolthreadpoolexecutor

提问by deadlock

I have a number of tasks inside a TheadPoolExecutor. I have a stop button on my interface that should terminate all the threads inside ThreadPoolExecutorimmediately. I am looking for a way to do it. (without shutDown()or shutDownNow()).

我在一个TheadPoolExecutor. 我的界面上有一个停止按钮,应该ThreadPoolExecutor立即终止里面的所有线程。我正在寻找一种方法来做到这一点。(没有shutDown()shutDownNow())。

Thanks

谢谢

回答by Peter Lawrey

You cannot safely kill threads immediately. You tasks should instead honour interrupts and stop when interrupted. If you use ThreadPoolExecutor.shutdownNow(), all the running tasks will be interrupted.

您不能立即安全地终止线程。你的任务应该尊重中断并在被中断时停止。如果使用ThreadPoolExecutor.shutdownNow(),所有正在运行的任务都会被中断。

The only alternative is to the threads in a separate process is issue a signal to kill the process.

唯一的替代方法是向单独进程中的线程发出信号以终止该进程。

回答by Dani C.

The shutdown()will only make the ThreadPoolExecutorto reject all new submited tasks, and remove from the queue (if the ThreadPoolis an unbounded queue executor) the pending tasks. The shutdownNow()will do exactly the same, and also will call to the interrupt()method of the Thread. So, in your run()method, you should handle it properly:

shutdown()只会使ThreadPoolExecutor拒绝所有新submited任务,并从队列中删除(如果ThreadPool是无界队列执行人)的尚未完成的任务。该shutdownNow()会做同样的,也将调用该interrupt()方法Thread。因此,在您的run()方法中,您应该正确处理它:

try {
   Thread.sleep(1000);
} catch (InterruptedException ie) {
   // Handle the exception, and close resources.
}

回答by Chetan Sharma

Old question but I think you can extend ThreadPoolExecutor to capture running Thread reference in beforeExecute(). When shutdownNow() would be called you can stop() all running Threads. Although I would strongly encourage relying on isInterrupted() in your tasks.

老问题,但我认为您可以扩展 ThreadPoolExecutor 以在 beforeExecute() 中捕获正在运行的线程引用。当 shutdownNow() 被调用时,你可以 stop() 所有正在运行的线程。尽管我强烈鼓励在您的任务中依赖 isInterrupted()。

Sample code ->

示例代码 ->

public class KillableThreadPoolExecutor extends ThreadPoolExecutor {

    private final Map<Runnable, Thread> executingThreads;

    public KillableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, String threadNamePrefix) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new YoungMemorySafeLinkedBlockingQueue<Runnable>(), ThreadFactories.create(threadNamePrefix));
        executingThreads = new HashMap<>(maximumPoolSize);
    }

    @Override
    protected synchronized void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        executingThreads.put(r, t);
    }

    @Override
    protected synchronized void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if(executingThreads.containsKey(r)) {
            executingThreads.remove(r);
        }
    }

    @Override
    public synchronized List<Runnable> shutdownNow() {
        List<Runnable> runnables = super.shutdownNow();
        for(Thread t : executingThreads.values()) {
            t.stop();
        }
        return runnables;
    }
}

回答by Ravindra babu

ThreadPoolExecutoris an ExecutorService. You can't stop all threads in ExecutorServiceeither with shutdown()or shutdownNow()methods. You have to call shutdown(), awaitTermination()and shutdownNow()methods in a sequence for graceful shutdown as quoted by oracle documentation page

ThreadPoolExecutor是一个ExecutorService。您不能在ExecutorServicewithshutdown()shutdownNow()methods 中停止所有线程。您必须按顺序调用shutdown(), awaitTermination()shutdownNow()方法才能正常关闭,如 oracle 文档页面所述

 void shutdownAndAwaitTermination(ExecutorService pool) {
   pool.shutdown(); // Disable new tasks from being submitted
   try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }
   } catch (InterruptedException ie) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }
 }

Other options:

其他选项:

  1. invokeAll()
  2. CountDownLatch
  3. Iterate through all Future.get()for all Callabletasks to achieve the same purpose.
  1. invokeAll()
  2. CountDownLatch
  3. 迭代通过所有Future.get()的所有Callable的任务来达到同样的目的。

回答by posdef

If you can use Callables instead of Runnables in your threads you could try and call someTask.cancel()to get rid of the running tasks at the time of shutdownNow()call.

如果您可以在线程中使用Callables 而不是Runnables ,则可以尝试调用someTask.cancel()以在调用时摆脱正在运行的任务shutdownNow()

Note that I have not tried this, so I can not guarantee it would work like you would like to, but judging from the javadoc description it's worth a try.

请注意,我还没有尝试过这个,所以我不能保证它会像你想要的那样工作,但从 javadoc 描述来看,它值得一试。