2

100回呼び出す必要があるメソッド名someTaskがあり、以下のように非同期コーディングを使用しています。

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

実行中に任意のスレッドで例外が発生した場合someTask()、現在のすべてのスレッドを中断し、将来のスレッドの実行も停止したいと考えています。これを処理する最善の方法は何ですか?

更新: を使用してThreadPoolTaskExecutorいます。

4

2 に答える 2

0

これを行うには多くの方法があり、すべてが正確なユース ケースに依存します。しかし、すべての方法 (と私は言います) には共通点が 1 つあります。それは、管理された方法でタスクを終了する必要があるということです。データの不整合やその他の問題が発生する可能性があるため、タスクの実行を単に「即時終了」することはできません。これは通常、フラグなどをチェックすることによって行われThread.isInterrupted()、実行がキャンセルされることを通知している場合は手動で実行を終了します。カスタム フラグを使用することもできます。

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();
    }
}

最後のタスクが例外をスローし、フラグcancelを に設定して処理していることに注意してくださいtrue。他のすべてのタスクは、定期的にチェックすることでそれを確認します。フラグがそれを示す場合、それらは実行をキャンセルします。例外をスローするタスクをコメントアウトすると、すべてのタスクが正常に終了します。

このアプローチは、使用されるエグゼキュータとは無関係であることに注意してください。

于 2020-06-29T22:59:14.130 に答える