【发布时间】:2020-09-21 13:45:42
【问题描述】:
我有一种生产者消费者问题的味道(我找不到任何类似的问题并且搜索关键字用完了)哪里
- 消费者本身就是生产者。
- 生产的物品可以共享。
- 如果某个线程正在生产,其他线程会等待它完成并使用相同的生产项目。
我想出了一个解决方案,但我不知道如何测试它。是否有理论框架来验证此类问题的解决方案的正确性。也可以在不修改源代码的情况下测试这些解决方案
如果您对代码感兴趣,请在下面列出
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
public class SharedItemProducer {
/* testing parameters */
static final int randMax = 1;
static final Random R = new Random();
static final int numThreads = 8;
static final long produceDelay = 0;
static final long maxRunTime = 5000;
Integer item = 0;
final Object waitingRoom = new Object();
AtomicInteger wantToBeProducer = new AtomicInteger(0);
public void produce() {
log("entering produce");
if (wantToBeProducer.compareAndSet(0, 1)) {
log("i'm the producer. cur=%d", item);
try {
Thread.sleep(produceDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
item = item + 1;
synchronized (waitingRoom) {
waitingRoom.notifyAll();
}
wantToBeProducer.set(0);
log("done producing");
} else {
log("someone else is producing, waiting..");
synchronized (waitingRoom) {
try {
waitingRoom.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log("wait complete");
}
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
/* run the tests */
SharedItemProducer1 P = new SharedItemProducer1();
for (int i = 0; i < numThreads; i++) {
new Thread(() -> {
while (true) {
P.produce();
try {
Thread.sleep(R.nextInt(randMax));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
/* limit time for tests */
new Thread(() -> {
try {
Thread.sleep(maxRunTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(0);
}).start();
}
static boolean enableLog = false;
static final String FMT = "[%s] [%s] ";
public static void log(String info, Object... params) {
if (!enableLog)
return;
Object[] pfParams = new Object[params.length + 2];
System.arraycopy(params, 0, pfParams, 2, params.length);
pfParams[0] = new Date();
pfParams[1] = Thread.currentThread().getName();
System.out.printf(FMT + info + "\n", pfParams);
}
}
【问题讨论】:
-
我建议仔细阅读the documentation of
wait,尤其是为什么它应该在循环中执行的解释(而测试条件必须包含在同一个synchronized块中)。当其他线程已经在wait()调用中时,当在synchronized块之外做出进入等待状态的决定时,期望notify()调用发生,这是一厢情愿的想法。跨度>
标签: java multithreading concurrency synchronization producer-consumer