20

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

谢谢

4

5 回答 5

16

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

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

于 2012-10-10T14:37:41.930 回答
7

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

示例代码 ->

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;
    }
}
于 2016-10-20T16:44:00.260 回答
6

shutdown()只会拒绝所有新提交的任务ThreadPoolExecutor,并从队列(如果ThreadPool是无界队列执行器)中删除待处理的任务。将shutdownNow()执行完全相同的操作,并且还将interrupt()调用Thread. 因此,在您的run()方法中,您应该正确处理它:

try {
   Thread.sleep(1000);
} catch (InterruptedException ie) {
   // Handle the exception, and close resources.
}
于 2012-10-10T14:41:03.943 回答
3

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

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

其他选项:

  1. invokeAll()
  2. CountDownLatch
  3. 遍历所有Future.get()任务Callable以达到相同的目的。
于 2016-10-20T18:52:30.320 回答
1

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

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

于 2012-10-10T14:44:43.833 回答