下面是消费者生产者的问题代码,但代码没有按预期工作。在这里,消费者和生产者应该只生产和消费一个对象。
public class ProducerConsumer {
private static LinkedList<Integer> linkedList = new LinkedList<>();
public static void main(String a[]) throws InterruptedException {
Thread producer = new Thread(new Runnable() {
@Override
public void run() {
synchronized(this) {
while (linkedList.size() == 1) {
try {
wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced");
linkedList.add(1);
notify();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread consume = new Thread(new Runnable() {
@Override
public void run() {
// produce
synchronized(this) {
while (linkedList.isEmpty()) {
try {
wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consumed");
linkedList.removeFirst();
notify();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
});
producer.start();
consume.start();
producer.join();
consume.join();
}
}
我们得到的输出是: Produced
然后程序就挂了。
请提供可能的解决方案/解释
发布于 2018-08-24 03:24:20
并发性意味着你不能在运行前知道哪个线程会先结束。因此,您无法知道Consumer和Producer中的哪一个是首先启动、执行或完成的。
为了给您提供帮助,您可以使用循环屏障https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html或应用分叉/连接框架https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html
你的同步块只是说:一次只有一个线程可以执行这部分代码,不能执行第一个和第二个之后的代码。
下面是CyclicBarrier工作原理的一个示例:
service = Executors.newFixedThreadPool(numThreadsTotal);
CyclicBarrier c = new CyclicBarrier(numThreadsToWait);
runProducer();
c.await();
runConsumer();
它将等待,直到有和numThreadsToWait一样多的线程执行runProducer来执行runConsumer()。
也许使用大小为1的线程池可以帮助您,但您将失去并发的好处。
发布于 2018-09-05 22:40:27
我认为你能做的最好的就是使用BlockingQueue。
https://stackoverflow.com/questions/51992862
复制相似问题