最近我一直在用“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)