Java 不同任务类型的闩锁
我正在寻找以下问题的java并发解决方案 有一些任务正在运行,还有一段代码CJava 不同任务类型的闩锁,java,concurrency,Java,Concurrency,我正在寻找以下问题的java并发解决方案 有一些任务正在运行,还有一段代码C C必须等待所有任务完成。(超时) 在C完成之前,不得开始任何任务 我查看了java.concurrency包,发现了一些有趣的东西,但似乎没有什么东西是正确的: 移相器允许单向阻塞,但不允许双向阻塞 信号量、ForkJoinTasks和其他一些都有计数器类型的特性,但它们似乎都不能满足我的要求 我相信我可以用一个相位器和一个锁来构造这样的东西: void C() { synchronized(lock)
- C必须等待所有任务完成。(超时)
- 在C完成之前,不得开始任何任务
- 移相器允许单向阻塞,但不允许双向阻塞
- 信号量、ForkJoinTasks和其他一些都有计数器类型的特性,但它们似乎都不能满足我的要求
void C() {
synchronized(lock) {
phaser.awaitAdvanceInterruptibly(phase, 1, TimeUnit.SECONDS);
// Start work anyway if a task is taking too long.
doWork();
}
}
void someTask() {
synchronized(lock) {
phaser.register();
}
doTask().thenRun(
() -> phaser.arriveAndDeregister()
);
}
现在,虽然我相当肯定这会起作用,但我也意识到尝试构建自己的并发解决方案是个坏主意。有更好的方法吗
如果没有,我将使用什么作为阶段
参数
编辑:此问题发生在涉及web客户端连接的项目中,因此任务的到达是不可预测的。但是,通过更仔细的设计可以避免这种情况。这是一个专门的用例,我认为我们需要使用多个并发实用程序进行协调。下面的程序应该可以做到这一点。请随时张贴问题的任何部分都不清楚-
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class TestClass {
private volatile int numOfActiveTasks = 0;
private Semaphore cSemaphore = new Semaphore(1);
private Semaphore taskSemaphore = new Semaphore(1);
private Object tasksLock = new Object();
//Test method
public static void main(String[] args) throws IOException {
TestClass testClass = new TestClass();
//Launch some task threads
ExecutorService taskES = Executors.newFixedThreadPool(2);
IntStream.range(1, 11).forEach((i) -> taskES.submit(() -> {
try {
testClass.executeTask();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
//Launch some C threads
ExecutorService cES = Executors.newFixedThreadPool(2);
IntStream.range(1, 5).forEach((i) -> cES.submit(() -> {
try {
testClass.C();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
taskES.shutdown();
cES.shutdown();
}
void C() throws InterruptedException {
try {
cSemaphore.acquire();
//If tasks are running, wait at-least n seconds
this.taskSemaphore.tryAcquire(1, TimeUnit.SECONDS);
print("C started running");
doCsWork();
} finally {
cSemaphore.release();
print("C stopped running");
}
}
void executeTask() throws InterruptedException {
//Do not start while C is running
cSemaphore.acquire();
cSemaphore.release();
synchronized (tasksLock) {
++numOfActiveTasks;
taskSemaphore.tryAcquire();
print("A task started running. Total " + numOfActiveTasks + " tasks running");
}
doTasksWork();
synchronized (tasksLock) {
--numOfActiveTasks;
if (numOfActiveTasks == 0) {
taskSemaphore.release();
}
print("A task stopped running. Total " + numOfActiveTasks + " tasks remaining");
}
}
void doCsWork() throws InterruptedException {
Thread.sleep(1000);
}
void doTasksWork() throws InterruptedException {
Thread.sleep(2000);
}
void print(String message) {
System.out.println(message);
}
}
我在java.util.concurrent.locks中找到了这个问题的解决方案,它非常适合我的用例
StampedLock lock;
void C() {
long stamp = lock.tryWriteLock(1, TimeUnit.SECONDS);
doWork();
lock.unlockWrite(stamp);
}
void someTask() {
long stamp = lock.readLock();
doTask().thenRun(() -> lock.unlockRead(stamp));
}
该类的关键在于readLock()不是独占的,而writeLock()是独占的。它还支持超时,类似于常规锁。您可以使用两个
countdownlock
s。一个用1创建,在C部分完成时启动任务;另一个用N创建,仅在N个任务完成时启动C部分finished@Ivan这将起作用,但我不知道将运行多少任务,或何时运行。我已经为这个问题添加了相关的上下文。C必须等待所有任务完成,但同时,任务不能开始,直到C完成。我是唯一一个在这里看到矛盾的人吗?@AlexeiKaigorodov C不依赖于任何任务的完成,但它必须等待任何正在进行的任务。因此,在C之后到达的任务必须等待C完成。