我没有得到下面程序的预期结果,我期望生产者和使用者方法都应按一定顺序执行,但由于某种原因,只有生产者方法正在执行。
我在这里有两个问题:
在main方法的最后一行将两个线程连接在一起正常,但我无法理解两者之间的区别。
public class ProducerConsumer {
List<Integer> data = new ArrayList<>();
synchronized void produce() throws InterruptedException {
for (int i = 0; i < 10; i++) {
System.out.println("Producing");
data.add(i);
}
wait();
}
synchronized void consume() throws InterruptedException {
System.out.println("Consuming");
data.clear();
notify();
}
public static void main(String[] args) throws InterruptedException {
ProducerConsumer pc = new ProducerConsumer();
Runnable r2 = ()-> {
try {
pc.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread1 = new Thread(r2);
thread1.start();
thread1.join();
Runnable r1 = () -> {
try {
pc.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread = new Thread(r1);
thread.start();
thread.join();
}
输出: 生产中 生产中 生产中 生产中 生产中 生产中 生产中 生产中 生产中 生产
答案 0 :(得分:1)
produce()
方法以wait()
结尾。因此它将阻塞,直到有线程通知它为止。
执行此操作的唯一线程是使用者线程。但是,只有在生产者线程结束之后,才通过main方法启动消费者线程。它直到被通知才结束。这样您就陷入僵局。
如果仅在启动两个线程之后join()
,则使用者线程可以启动而不必等待生产者线程完成。自那以来,这仍然不能使程序正确
答案 1 :(得分:0)
1)notify()
调用根本不执行任何操作。除非其他线程已经已经等待要通知。
由您保证,只要您的一个线程调用wait()
的任何时间,其他线程在{{1}之后的某个时间notify()
都会同一个对象}已经开始。
Oracle的Guarded Blocks Tutorial很好地解释了wait()
和o.wait()
的工作原理,并解释了如何建立保证。
2)几乎没有理由这样做:
o.notify()
您的程序将使用较少的CPU,并且将使用较少的内存,并且如果您只是调用Thread t = new Thread(r);
t.start();
t.join();
,则它将完成完全相同的操作。线程的整个点是为了允许发生不同的事情 concurrently ,并且如果一个线程r.run()
之后紧接一个新线程,则不会并发创建它。除非您使用新的joins
对象,否则将被浪费掉:
Thread
3)Thread t = new Thread(r);
t.start();
doSomethingElseWhileThread_t_isRunning();
t.join();
和wait()
是线程之间进行通信的非常底层的方法。如果您使用在notify()
和wait()
之上构建的higher-level synchronization objects而不是直接构建,则代码将更易于阅读和理解。
打电话给他们。
java.util.concurrent.ArrayBlockingQueue
实例将特别适合于“生产者/消费者”应用程序。