最近我一直在用“ReentrantLock”重构我的项目以简化逻辑。
总体思路是:
1.“主”可运行线程独立运行
2. 如果一切正常,主线程将等待条件“nextStep”
3. 当发生错误时,“onCancel()”方法将被另一个线程调用,迫使主线程抛出InterruptionExcpetion,从而发生关闭
经过一番测试,得出了我自己的方法:
doInterrupt();
从未按预期工作:强制主线程进入“InterruptedException”子句并退出循环。
更新2:
我已经在所有输出日志行中添加了一条“被中断”调试消息,如果事实证明中断状态被某人“神秘地”清除了......
更新:
锁定和条件方法:
lock.lockInterruptibly();
condition.await();
有时似乎没有检查中断状态? .... javadoc 内容如下:
...... If the current thread: has its interrupted status set on entry to this method; or is interrupted while acquiring the lock, then InterruptedException is thrown and the current thread's interrupted status is cleared. ......
from the log it could see something like:
[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)
最佳答案
仔细检查“process()”中使用的每一个方法后,发现有一个方法不小心“吞噬”了InterruptionException...
只需抛出异常,整个代码/类现在就按预期工作了~~~
非常感谢“@hendalst”,他在我的帖子中发表了评论,使我修改了所有可能的中断泄漏......正如您所说:“上面的代码有效”,根本原因方法在评论区域内“//一些工作。 ..”我没有在这里发布...
并感谢“@orionll”关于编码原则的建议
关于java - ReentrantLock -> lockInterruptically() 有时不会检查中断状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16518706/