0

N 個のスレッドがあり、各スレッドは独自のメンバ変数 "status" でステータスを 0 または 1 に設定します。呼び出し側で、いずれかのスレッドのステータスが 1 の場合、全体のステータスが 1 になる必要があります。

これらのスレッドはバッチ モードで実行されます。そのため、いずれかが失敗した場合は、すべてを再実行する必要があります。残りのスレッドもすぐに停止するように、失敗を処理するための処理を考え出す必要があります。

スレッドは実行可能ですが、呼び出し可能ではありません。

失敗を通知する揮発性ブール変数を使用して、スレッド間で通信できます。ただし、呼び出し元で実行可能なスレッドから個々のステータスを読み取る方法を知る必要がありました。

4

2 に答える 2

3

これを達成するにはいくつかの方法があります。1 つの方法は、補完サービスを使用することです。ここにいくつかの(大まかにテストされた)コードがあります:

public void allSucceed(final List<MyRunnable> tasks) {
    if (tasks == null || tasks.size() == 0)
        return;

    int status = 0;

    boolean success = true;
    do {
        final ExecutorService executorService = Executors
                .newFixedThreadPool(tasks.size());
        final CompletionService<MyRunnable> completionService = new ExecutorCompletionService<MyRunnable>(
                executorService);
        for (final MyRunnable task : tasks) {
            completionService.submit(task, task);
        }

        for (int i = 0; i < tasks.size(); i++) {
            try {
                status = completionService.take().get().getStatus();
            } catch (final Exception e) {
                success = false;
                break;
            }

            if (status == 0) {
                System.out.println("A task failed. All will be rerun");
                executorService.shutdownNow();
                success = false;
                break;
            }
        }
    } while (!success);
}

タスク (Runnables) を中断できるように設計することが重要です。そうしないと、それらを停止しようとしても無駄になります。

于 2013-02-20T19:10:09.530 に答える
1

呼び出し元のスレッドに値を設定するようスレッドに要求するだけです。

呼び出し元のフィールド:

int[] status = new int[NUM_THREADS];

次に、各 Runnable にインデックスを付けて、配列でステータスを設定できるようにします。次に例を示します。

for (int i = 0; i < NUM_THREADS; i++) {
    final index = i;

    Runnable r = new Runnable() {
        void run() {
            // have your code stop occasionally to check for any failures
            if (>I failed>)
                status[index] = 1;
        }
    }
    // start thread using Runnable
}

停止を検出するには、Runnables で arraym の障害をときどきチェックするかboolean、呼び出し元クラスに別のフラグを追加することができます。

volatile boolean failed = false;
Object lock = new Object();

次に、ランナブルで:

if (<I failed>) {
    synchronised (lock) {
        failed = true;
    }
}

作業中の失敗のチェックは次のようになります。

synchronised (lock) {
    if (failed) {
        // clean up resources
        status[index] = -1; // consider using a separate value for "halted"
        return;
    }
}
于 2013-02-20T19:04:08.920 に答える