【发布时间】:2019-11-13 02:57:10
【问题描述】:
我的应用程序中有一种情况,即事件进入并且处理它们的线程(信号线程)必须向另一个线程(工作线程)发出信号,到目前为止它处于空闲状态,它可以运行一些代码。一旦工作线程完成,它应该等待再次发出信号。工作线程正在工作时,事件可能会到达。在这种情况下,它应该继续前进并立即继续工作。工作线程的一个动作对任何数量的传入事件都足够工作,因此不需要每个事件工作一次,只需在每个事件之后尽快工作一次。正确行为示例:
event comes in
worker thread starts work
worker thread finishes work
event comes in
worker thread starts work
event comes in
event comes in
worker thread finishes work
worker thread starts work
worker thread finishes work
4 个事件,3 个工作周期。这是一个不幸但不可避免的要求,即信号线程在处理事件时不能阻塞。目前我已经使用 BlockingQueue 实现了这一点,它具有填充自身的无意义的副作用,即使内容不有趣甚至看起来也不有趣。我希望能够使用 CountDownLatch 或 CyclicBarrier 或类似方法来完成这项工作,但我一直找不到方法。这是我的实现:
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
private static final class MyBarrier {
private BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
void await() throws InterruptedException {
queue.take();
queue.clear();
}
void signal() {
queue.add(true);
}
}
private static Random random = new Random(0);
private static void sleepForMax(int maxMillis) {
sleep(random.nextInt(maxMillis));
}
private static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public static void main(String[] args) {
MyBarrier myBarrier = new MyBarrier();
final ExecutorService singallingThread = Executors.newSingleThreadExecutor();
singallingThread.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
sleepForMax(1_000); // simulate period between events arriving
myBarrier.signal();
System.out.println("Signalling work to be done");
}
System.out.println("Thread interrupted");
});
final ExecutorService workingThread = Executors.newSingleThreadExecutor();
workingThread.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("Waiting for work");
myBarrier.await();
} catch (InterruptedException e) {
break;
}
System.out.println("Doing work...");
sleepForMax(3_000); // simulate work being done
System.out.println("Work done");
}
System.out.println("Thread interrupted");
});
sleep(10_000);
singallingThread.shutdownNow();
workingThread.shutdownNow();
}
}
有什么更好的方法来做到这一点?
【问题讨论】:
标签: java multithreading concurrency java.util.concurrent