最近、ロジックを簡素化するために、「ReentrantLock」を使用してプロジェクトをリファクタリングしています。
一般的な考え方は次のとおりです。
1. 「メイン」の実行可能なスレッドが独自に実行されている
2. すべてが正常な場合、メイン スレッドは条件「nextStep」で待機し
ます 3. 何か問題が発生した場合、メソッド「onCancel()」が呼び出されます/別のスレッドで、メイン スレッドに InterruptionExcpetion を強制的にスローさせるため、シャットダウンが発生します。
いくつかのテストの後、それは私自身の方法であることがわかりました:
doInterrupt();
期待どおりに機能しませんでした: メインスレッドに強制的に "InterruptedException" 句を入力させ、ループを終了させます。
UPDATE-2:
すべての出力ログ行に「is-interrupted」デバッグ メッセージを追加しました。割り込み状態が「謎めいた」誰かによってクリアされたことが判明した場合...
UPDATE:
ロックおよび条件メソッド:
lock.lockInterruptibly();
condition.await();
時々割り込み状態をチェックしていないようでしたか?.... javadoc には次のように書かれています。
…… 現在のスレッドの場合: このメソッドへのエントリで割り込みステータスが設定されます。また ロックの取得中に中断された、 次に InterruptedException がスローされ、現在のスレッドの中断ステータスがクリアされます。 ……
ログから、次のようなことがわかります。
[action] waiting for completion...: 1 [is-interrupted:false]
>> DEBUG ---> will begin next loop [is-interrupted:false]
[action] reset for next iteration: 2 [is-interrupted:false]
[action] cancelling... [is-interrupted:false]
>> DEBUG ---> will interrupt [is-interrupted:false]
>> DEBUG ---> check. [is-interrupted:true]
[action] waiting for completion...: 2 [is-interrupted:false]
>> DEBUG ---> will begin next loop [is-interrupted:false]
[action] reset for next iteration: 3 [is-interrupted:false]
[action] waiting for completion...: 3 [is-interrupted:false]
>> DEBUG ---> will begin next loop [is-interrupted:false]
[action] reset for next iteration: 4 [is-interrupted:false]
[action] waiting for completion...: 4
>> DEBUG ---> will begin next loop
[action] reset for next iteration: 5
[action] waiting for completion...: 5
>> DEBUG ---> will begin next loop
[action] reset for next iteration: 6
...... and so on until i == max
[info] main process has reached a finish state.
これは基本的に、割り込み信号が失われたか、何らかの形で処理されていないことを意味します...
より良いアプローチはありますか?または少なくとも私のコードロジックの修正?
マルチスレッドの専門家はいますか???
これが私のコードです:
public class SBCSTaskEngine extends GenericEngine<SBCSTask> implements XListener {
private final ReentrantLock lock = new ReentrantLock();
private final Condition nextStep = lock.newCondition();
private volatile Thread main = null;
// something else ...
// it's a runnable "MAIN"
@Override
protected void run() {
try {
main = Thread.currentThread();
// some setting up... x is between 1 ~ 10000
for (int i = 1; i <= max; i++) {
lock.lockInterruptibly();
// some work ...
log("[action] waiting for completion...: " + i);
// a very long wait (could be REALLY fast if task went south)
nextStep.await();
if (max == i) {
isNormalCompletion = true;
} else {
log("[action] reset for next iteration:" + (i+1));
// some reset work...
}
lock.unlock();
} // end of [for] loop
} catch (InterruptedException e) {
log("[event] process stopped by singal.");
} finally {
try { lock.unlock(); } catch (Throwable ignored) {}
}
log("[info] main process has reached a finish state.");
}
private void doInterrupt() {
log(">> DEBUG ---> will interrupt");
if (main != null)
main.interrupt();
log(">> DEBUG ---> check.");
}
/**
* implement: XListener(series)
* instruct main process to enter cancel sequence
*
* known-issue: duplicate call? sync on method? wait for risk evaluation
*/
@Override
public void onCancel() {
log("[action] cancelling...");
doInterrupt();
}
/**
* implement: XListener(series)
* proceed the main thread to next loop
*
* known-issue: signal might occur before all "memebers" could await on the condition (happen-before?), just take the chance for now...
*/
@Override
private void doNotifyNextStep() {
try {
lock.lockInterruptibly();
log(">> DEBUG ---> will begin next loop");
nextStep.signalAll();
} catch (InterruptedException e) {
doInterrupt();
} finally {
try { lock.unlock(); } catch (Throwable ignored) {}
}
}
} // end of [SBCSTaskEngine] class
詳細情報: 私が使用した Java バージョン:
java version "1.6.0_26" Java(TM) SE Runtime Environment (build 1.6.0_26-b03) Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)