如何在线程池中停止线程

use*_*045 8 java

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

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

我的问题:如何停止当前正在运行的任务?我实现的解决方案是存储对任务线程的引用并调用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

主要方法是:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Rad*_*der 5

您可以通过保留对未来的引用来阻止它

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

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

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

如果你有cachedThreadPool,你可能需要仔细检查你的可运行对象中是否捕获了异常,然后不要设置回中断标志,因为你的线程将运行另一个未来,如果你设置中断,另一个队列未来可能不会运行。


Qwe*_*rky 2

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