1

最近、ロジックを簡素化するために、「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)
4

1 に答える 1