java - 当另一个线程启动时终止一个线程

标签 java multithreading synchronization thread-safety

基本上,我有一个很长的任务,由一堆序列子任务组成,如下所示:

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/

相关文章:

java - EclipseLink DDL 创建带有小数秒的 MySql DATETIME

java - 使用sql2o时,org.sql2o.converters.ConverterException是什么?

java - 线程池中要创建多少个线程

使用集合时线程安全的 C# 最佳实践(还不是并发的)

Java:通过反射多次访问同步方法?

java - Spring websockets - 分离 MessageMapping 和 SendTo

java - 使用自定义主要工件发布 Java 库

c# - Monitor.TryEnter 不起作用

java - 从 spring mvc 应用程序提交后台任务

c# - 如何将软实时数据从 Matlab 流式传输到 C# 应用程序?