基本上,我有一个很长的任务,由一堆序列子任务组成,如下所示:
class Task implements Runnable
{
private Foo foo;
public Task(Foo foo)
{
this.foo = foo;
}
@Override
public void run()
{
doTask1(foo);
doTask2(foo);
doTask3(foo);
doTask4(foo);
// ...
doTaskN(foo);
}
}
我需要的是仅运行Task
的一个实例,如果一个Task
开始,则其他Task
(如果有) )应立即终止。
我使用了单线程执行器:
Executor executor = Executors.newSingleThreadExecutor();
我运行任务:
executor.execute(new Task(foo));
这保证了一次只执行一个任务,但不幸的是它不会终止之前的任务。
<小时/>但是,我决定在每 2 个子任务之间使用 boolean 标志,如下所示:
class BooleanHolder
{
boolean terminate = false;
}
class Task implements Runnable
{
private Foo foo;
private BooleanHolder bh;
public Task(Foo foo, BooleanHolder bh)
{
this.foo = foo;
this.bh = bh;
}
@Override
public void run()
{
bh.terminate = false;
doTask1(foo);
if(bh.terminate) return;
doTask2(foo);
if(bh.terminate) return;
doTask3(foo);
if(bh.terminate) return;
doTask4(foo);
// ...
if(bh.terminate) return;
doTaskN(foo);
}
}
并像这样使用它:
BooleanHolder bh = new BooleanHolder();
// ...
bh.terminate = true;
executor.execute(new Task(foo, bh));
但是,这似乎是低效的解决方案并且不是线程安全的。您有更好的解决方案吗?
最佳答案
您应该使用 ExecutorService
接口(interface),而不是 Executor
,如下所示:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(new Task(foo));
然后您可以通过cancel
方法中断正在运行的任务以执行另一个任务:
future.cancel(true);
正如 @RPT 所说,您应该以响应中断的方式构建任务,否则中断信号将不会产生任何效果。如果您的任务没有引发 InterruptedException
的操作,您应该不时手动检查中断标志(类似于您已经执行的操作):
@Override
public void run()
{
....
if (Thread.interrupted()) {
// Release resources and end task
}
....
}
顺便说一句,这解决了您的问题,但实际上并没有终止 ExecutorService 内的线程。
关于java - 当另一个线程启动时终止一个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11507492/