Java 如何停止线程池中的线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3777772/
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-08-14 04:52:01  来源:igfitidea点击:

how to stop a thread in a threadpool

java

提问by user456045

I'm writing an application that spawns multiple concurrent tasks. I'm using a thread pool to implement that.

我正在编写一个产生多个并发任务的应用程序。我正在使用线程池来实现它。

It may happen that an event occurs that renders the computations being done in the tasks invalid. In that case, I would like to stop the currently running tasks, and start new ones.

可能会发生使任务中正在执行的计算无效的事件发生。在这种情况下,我想停止当前正在运行的任务,并开始新的任务。

My problem: How do I stop the currently running tasks? The solution I implemented is to store a reference to the task thread and call interrupt()on this thread. In demo code:

我的问题:如何停止当前正在运行的任务?我实现的解决方案是存储对任务线程的引用并调用interrupt()该线程。在演示代码中:

public class Task implements Runnable {

    private String name;
    private Thread runThread;

    public Task(String name) {
        super();
        this.name = name;
    }

    @Override
    public void run() {
        runThread = Thread.currentThread();

        System.out.println("Starting thread " + name);
        while (true) {
            try {
                Thread.sleep(4000);
                System.out.println("Hello from thread " + name);
            } catch (InterruptedException e) {
                // We've been interrupted: no more messages.
                return;
            }
        }
    }

    public void stop() {
        runThread.interrupt();
    }

    public String getName() {
        return name;
    }
}

And the main method is:

主要方法是:

public static void main(String args[]) {
    executorService = Executors.newFixedThreadPool(2);

    Task t1 = new Task("Task1");
    Task t2 = new Task("Task2");
    executorService.execute(t1);
    executorService.execute(t2);
    executorService.execute(new Task("Task3"));
    executorService.execute(new Task("Task4"));

    try {
        Thread.sleep(12000);
        t1.stop();
        System.err.println("Stopped thread " + t1.getName());
        Thread.sleep(8000);
        t2.stop();
        System.err.println("Stopped thread " + t2.getName());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Is this a good solution, or is there a better way to stop a running thread in a thread pool?

这是一个很好的解决方案,还是有更好的方法来停止线程池中正在运行的线程?

回答by Qwerky

In your overridden run()method you loop forever with while(true). The standard behaviour would be to have a boolean runIndicatorwhich the run()method sets to true when it starts, and your loop should then be while(runIndicator). Your stop()method should simple set runIndicator = falseso the next iteration of the loop will fall out.

在您覆盖的run()方法中,您将永远循环使用while(true). 该标准的行为将有一个boolean runIndicatorrun()方法设置为true,在启动时,然后你的循环应该是while(runIndicator)。您的stop()方法应该简单设置,runIndicator = false以便循环的下一次迭代会失败。

回答by Thirler

The idea behind your approach is one of the several correct solutions. Dealing with InterruptedExceptiongives a great rundown on how you should use the interrupt mechanism. This mechanism is mainly useful when you are long computations. One other thing to keep in mind is that it is possible for other libraries to spoil your interrupt mechanism by not doing what the guide says (not resetting the interrupt state when they haven't handled it etc).

您的方法背后的想法是几种正确的解决方案之一。处理 InterruptedException对如何使用中断机制提供了一个很好的总结。当您进行长时间计算时,此机制主要有用。要记住的另一件事是,其他库可能会破坏您的中断机制,因为他们不按照指南说的去做(在他们没有处理中断状态时不重置中断状态等)。

Do note that your Taskclass isn't thread-safe. You could be stopping the task before saving the currentThread, which would give a NullPointerException.

请注意,您的Task类不是线程安全的。您可能会在保存之前停止任务currentThread,这会产生 NullPointerException。

A much simpler approach is to set a volatile booleanvariable runningand instead of a while(true)loop doing a while(running)approach (this is however much more general).

一个更简单的方法是设置一个volatile boolean变量running而不是一个while(true)循环来做一个while(running)方法(但是这更通用)。

Another thing to look at is the FutureTaskmechanism, as this already has a canceling mechanism that uses the interrupt mechanism.

另一个需要考虑的是FutureTask机制,因为它已经有一个使用中断机制的取消机制。

回答by Jaydeep Patel

executorService.shutdown() and executorService.shutdownNow() should be used to shutdown the thread pool to gracefully exiting the application. See ExecutorService.

executorService.shutdown() 和 executorService.shutdownNow() 应该用于关闭线程池以优雅地退出应用程序。请参阅ExecutorService

See Qwerky's answer for ending the currently running thread.

请参阅 Qwerky 的回答以结束当前正在运行的线程。

回答by Radu Toader

You can stop it by holding a reference to that future

你可以通过持有对那个未来的引用来阻止它

          Future<?> future = exec.submit( new Runnable() {
      while (true){
        try{ 
          obj.wait();
      }catch(InterruptedException e){
          System.out.println("interrupted");
          return;
       }
      });
      future.cancel(true);

boolean is for - may interrupt if running.

布尔值用于 - 如果运行可能会中断。

I tested out and got an interrupted exception from that thread.

我进行了测试,并从该线程中得到了一个中断的异常。

If you have cachedThreadPool you may want to double check that you catch the exception in your runnable, and then don't set back the flag interrupted, because your thread will run another future, if you set interrupt, the other queue future may not run.

如果你有 cachedThreadPool 你可能想仔细检查你在 runnable 中捕获异常,然后不要设置中断标志,因为你的线程将运行另一个未来,如果你设置了中断,另一个队列未来可能不会运行.