1

最近我一直在用“ReentrantLock”重构我的项目以简化逻辑。

总体思路是:

1. "main" 可运行线程自己运行
2. 如果一切正常,主线程将等待条件 "nextStep"
3. 当发生错误时,将调用方法 "onCancel()" /在另一个线程中,强制主线程抛出一个InterruptionExcpetion,所以会发生关机

经过一些测试,结果是我自己的方法:

doInterrupt(); 

从未按预期工作:强制主线程进入“InterruptedException”子句并退出循环。

UPDATE-2:
我已经在所有输出日志行中添加了“被中断”调试消息,如果结果证明中断状态被某个人“神秘地”清除了......

更新:
锁定和条件方法:



     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

0

仔细检查了“process()”中使用的每一个方法,结果发现有一个方法不小心“吞下了”InterruptionException......

只需抛出异常,整个代码/类现在就可以正常工作了~~~

非常感谢“@hendalst”,他在我的帖子中发表了评论,让我修改了所有可能的中断泄漏......正如你所说:“上面的代码有效”,根本原因在评论区域内“//一些工作。 ..” 我没有在这里发布...

感谢“@orionll”关于编码原则的建议

于 2013-05-14T02:15:14.620 回答