我正在使用CountDownLatch在执行某些代码之前等待N个操作完成,同时给出超时以确保即使并非所有N个操作都已完成也会执行最终代码。 即:
CountDownLatch latch= new CountDownLatch(N);
latch.await(20, TimeUnit.MINUTES);
//Some code
我希望20分钟超时是动态的,因此每次锁存器倒计时都会重置,所以只有在自上次倒计时20分钟后锁存器才会退出等待(或者正常的情况,当它收到N次倒计时)。这有什么支持吗?
答案 0 :(得分:0)
您可以在自己的CountDownLatch
中实施此功能。您可以保留调用方法countDown()
的时间戳,将其与等待开始时的时间戳进行比较,调整等待时间,如果时间戳不同则再次等待。例如,
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
public class MyCountDownLatch extends CountDownLatch {
private AtomicLong timestamp;
public MyCountDownLatch(int count) {
super(count);
timestamp = new AtomicLong(System.nanoTime());
}
@Override
public void countDown() {
super.countDown();
timestamp.set(System.nanoTime());
}
public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException {
long start = timestamp.get();
long diff = 0;
for (;;) {
boolean result = await(unit.toNanos(timeout) - diff, TimeUnit.NANOSECONDS);
if (timestamp.get() == start) return result;
start = timestamp.get();
diff = System.nanoTime() - start;
}
}
}
这是一个测试程序:
import java.time.LocalTime;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) throws InterruptedException {
MyCountDownLatch latch = new MyCountDownLatch(3);
// Create three workers and give them different work time
Worker worker1 = new Worker("A", 1, latch);
Worker worker2 = new Worker("B", 3, latch);
Worker worker3 = new Worker("C", 5, latch);
List<Worker> workers = Arrays.asList(worker1, worker2, worker3);
// Start the workers
workers.forEach(Worker::start);
// Wait until the latch to count down to zero, or no countdown in
// 3 seconds.
boolean result = latch.waitFor(3, TimeUnit.SECONDS);
System.out.printf("%s | latch.waitFor() returns %b\n", LocalTime.now(), result);
// Terminate those workers who are still running
workers.stream().filter(Worker::isAlive).forEach(Worker::interrupt);
}
static class Worker extends Thread {
private String name;
private int workTime;
private CountDownLatch latch;
public Worker(String name, int workTime, CountDownLatch latch) {
this.name = name;
this.workTime = workTime;
this.latch = latch;
}
@Override
public void run() {
try {
System.out.printf("%s | Worker %s started\n", LocalTime.now(), name);
Thread.sleep(workTime * 1000L);
System.out.printf("%s | Worker %s finished\n", LocalTime.now(), name);
} catch (InterruptedException e) {
System.out.printf("%s | Worker %s interrupted\n", LocalTime.now(), name);
} finally {
latch.countDown();
}
}
}
}