如果任何线程中发生异常,则中断所有线程 [英] Interrupt all threads if an exception occurs in any

查看:260
本文介绍了如果任何线程中发生异常,则中断所有线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个方法名称 someTask ,我必须调用100次,并且使用如下所示的异步编码。

I have a method name someTask that I have to invoke 100 times and I am using asynchronous coding as below.

for (int i = 0; i < 100; i++) { 
    futures.add(CompletableFuture.supplyAsync(  
       () -> { someTask(); }, 
       myexecutor
    ));
}

如果在执行 someTask()时任何线程上发生异常我想中断所有当前线程,也要停止将来的线程执行。最好的处理方法是什么?

If an exception occurs on any thread while executing someTask() I want to interrupt all the current threads and also stop future threads from executing. What is the best way to handle this?

更新
我正在使用 ThreadPoolTask​​Executor

推荐答案

有很多方法可以做到这一点,并且都取决于确切的用例。但是,所有方式(我想说)都有一个共同点:您必须以可控的方式结束任务。您不能只是即时终止,执行任务,因为这可能导致数据不一致和其他问题。这通常是通过检查一些标志来完成的,例如 Thread.isInterrupted(),如果它表示执行将被取消,则手动结束执行。您也可以使用一个自定义标志,该标志将显示:

There are many ways to do that and all depend on the exact use case. But all ways (I'd say) have one thing in common: you'll have to end the tasks in a controlled manner. You can't just "instant-terminate" the execution of a task because this could lead to inconsitent data and other problems. This is usually done by checking some flag, e.g. Thread.isInterrupted(), and ending the execution manually if it's signaling that the execution shall cancel. You can use a custom flag as well, which I'll show:

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

class Main  {
    
    static final ExecutorService executor = Executors.newCachedThreadPool();
    
    
    // just dummy stuff to simulate calculation
    static void someStuff(AtomicBoolean cancel) {
        if (cancel.get()) {
            System.out.println("interrupted");
            return;
        }
        System.out.println("doing stuff");
        for (int i = 0; i < 100_000_000; i++) {
            Math.sqrt(Math.log(i));
        }
    }
    
    
    static void someTask(AtomicBoolean cancel) {
        someStuff(cancel);
        someStuff(cancel);
        someStuff(cancel);
    }
    
    
    public static void main(String[] args) {
        final Set<CompletableFuture<?>> futures = new HashSet<>();
        final AtomicBoolean cancel = new AtomicBoolean();
        
        for (int i = 0; i < 10; i++) { 
            futures.add(CompletableFuture.supplyAsync(  
               () -> {someTask(cancel); return null;}, executor
            ));
        }
        futures.add(CompletableFuture.supplyAsync(() -> {
            try {
                throw new RuntimeException("dummy exception");
            }
            catch (RuntimeException re) {
                cancel.set(true);
            }
            return null;
        }));
        
        futures.forEach(cf -> cf.join());
        executor.shutdownNow();
    }
}

请注意,最终任务正在抛出异常并通过设置异常来处理将取消标记为 true 。其他所有任务将通过定期检查来查看。如果标志发出信号,它们将取消执行。如果您将抛出异常的任务注释掉,则所有任务都将正常完成。

Notice that the final task is throwing an exception and handles it by setting the flag cancel to true. All the other tasks will see that by checking it periodically. They will cancel their execution if the flag signals it. If you comment out the exception-throwing task, all tasks will just finish normally.

请注意,此方法与所使用的执行程序无关。

Note that this approach is independent of the executor used.

这篇关于如果任何线程中发生异常,则中断所有线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆