共享物品的生产者和消费者问题
Shared item producers and consumer problem
我遇到了生产者消费者问题(我在搜索关键字中找不到任何类似的问题和 运行),其中
- 消费者本身就是生产者。
- 制作的物品可以分享。
- 如果某个线程正在生产,其他线程会等待它完成并使用相同的生产项目。
我想出了一个解决方案,但我对如何测试它一头雾水。是否有一个理论框架来验证解决此类问题的正确性。也可以在不修改源代码的情况下测试这些解决方案
如果您对代码感兴趣,下面列出了它
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);
}
}
如果我没理解错的话,您是在寻求一种控制线程交错的方法,以便您可以验证可能的边缘情况和奇怪的情况。
我建议您看看 Baeldung - Testing Multi-Threaded Code in Java 看看是否有帮助。
它不仅讨论了测试并发代码的概念和策略,还提到了一些可能有用的工具,包括:
请看看并试一试。
为了更好地测试您的代码,我还建议您将其进一步模块化,这样您就可以单独测试生产者和消费者。
编辑: 要提出测试用例,列出您可能希望在代码中验证的典型并发问题可能会有所帮助。请查看来自名为 Testing Concurrent Systems: Concurrency Defects, Testing Techniques, and Recommendations 的 CMU SEI 的博客 post,以获得详尽的列表。
我遇到了生产者消费者问题(我在搜索关键字中找不到任何类似的问题和 运行),其中
- 消费者本身就是生产者。
- 制作的物品可以分享。
- 如果某个线程正在生产,其他线程会等待它完成并使用相同的生产项目。
我想出了一个解决方案,但我对如何测试它一头雾水。是否有一个理论框架来验证解决此类问题的正确性。也可以在不修改源代码的情况下测试这些解决方案
如果您对代码感兴趣,下面列出了它
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);
}
}
如果我没理解错的话,您是在寻求一种控制线程交错的方法,以便您可以验证可能的边缘情况和奇怪的情况。
我建议您看看 Baeldung - Testing Multi-Threaded Code in Java 看看是否有帮助。
它不仅讨论了测试并发代码的概念和策略,还提到了一些可能有用的工具,包括:
请看看并试一试。
为了更好地测试您的代码,我还建议您将其进一步模块化,这样您就可以单独测试生产者和消费者。
编辑: 要提出测试用例,列出您可能希望在代码中验证的典型并发问题可能会有所帮助。请查看来自名为 Testing Concurrent Systems: Concurrency Defects, Testing Techniques, and Recommendations 的 CMU SEI 的博客 post,以获得详尽的列表。