有没有什么方法可以显式释放CountDownLatch
- 意味着没有 do countDown()
。
例如:假设我正在等待 100 个线程来做countDown()
,但是如果出现故障,我想释放这个闩锁而不再等待。我正在考虑先getCount()
锁定然后再循环执行countDown()
,但这不是最佳方式。
有什么建议/想法吗?
有没有什么方法可以显式释放CountDownLatch
- 意味着没有 do countDown()
。
例如:假设我正在等待 100 个线程来做countDown()
,但是如果出现故障,我想释放这个闩锁而不再等待。我正在考虑先getCount()
锁定然后再循环执行countDown()
,但这不是最佳方式。
有什么建议/想法吗?
The CountDownLatch has an overloaded await() method which takes time and time unit as inputs and releases the lock once the given time elapses
为什么不直接使用等待超时?
boolean await(long timeout, TimeUnit unit);
如果指定的等待时间过去,则返回值 false,否则在等待完成时返回 true。
如果您想停止其他线程的执行,如果任何线程失败 - 您将需要一些额外的通信层。
例如:
AtomicBoolean kill = new AtomicBoolean(false);
CountDownLatch latch = new CountDownLatch(SOME_NUM);
class Task extends Runnable {
public void run() {
try {
....
if (kill.get())
throw new Exception();
....
} catch (Throwable throwable) {
kill.set(true);
} finally {
countDownLatch.countDown();
}
}
}
如果您只想释放 Throwable 的倒计时,而不管其他进程,您可以在 Exception 的循环中执行 countDown
class Task extends Runnable {
public void run() {
try {
....
} catch (Throwable throwable) {
while(countDownLatch.getCount() != 0)
countDownLatch.countDown();
} finally {
countDownLatch.countDown();
}
}
}
您可以组合 2 个倒计时任务
CountDownLatch A = new CountDownLatch(1);
CountDownLatch B = new CountDownLatch(1);
class CountDownTracker extend Runnable {
public void run() {
B.await();
A.countDown();
}
}
class Task extends Runnable {
public void run() {
try {
....
} catch (Throwable throwable) {
A.countDown();
} finally {
B.countDown();
}
}
}
在这种情况下,A 将在完成或任何任务失败后完成。
等等...
You could use a Semaphore
, which is close to a CountDownLatch
and it's impl has methods for manipulating it: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html
除了其他答案:
这取决于“但如果某事失败”的含义,但如果失败意味着您在工作线程中捕获了异常,您也可以在 catch 子句中倒计时。这当然将 countDown 的含义从“成功处理”更改为“处理完成” - 所以你的代码必须处理这个..
检查您的用例是否允许通过键盘交互输入来解决问题。然后,您可以期望在 System.in 中手动输入,而不是 CoundDownLatch 或 Semaphore:
Scanner sc = new Scanner(System.in);
sc.nextLine();
如果您在单元测试中需要它,请确保您的环境已设置为读取用户输入,例如使用-Deditable.java.test.console=true
“帮助”->“编辑自定义 VM 选项...”中的选项启动 IntelliJ Idea