生产者-消费者模型
生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
解决方法就是一个线程负责生产数据,放到共享区域,然后通知另一个线程去消耗数据。如果没有wait()和notify(),消费者线程就要不停去检查是否有数据被产生。
代码如下:
package produce_consume;
import java.util.*;
import java.util.List;
import thread_test.test1;
class Resource{
//生产上限
final int MAX = 10;
List<String> list = new LinkedList<String>();
public synchronized void produce(){
while (list.size() > MAX) {
System.out.println("生产过剩,等待消费");
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
list.add("资源");
System.out.println("正在生产");
notify();
}
public synchronized void consume(){
while (list.size() <= 0) {
System.out.println("生产不足,等待生产");
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
list.remove(0);
System.out.println("正在消费");
notify();
}
}
class MyThread implements Runnable{
String name;
Resource resource;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MyThread(String name,Resource resource){
this.name = name;
this.resource = resource;
}
@Override
public void run() {
if (this.name.equals("生产者")) {
resource.produce();
}
if (this.name.equals("消费者")) {
resource.consume();
}
}
}
public class Test {
public static void main(String[] args) {
Resource resource = new Resource();
while (true) {
Thread t1 = new Thread(new MyThread("消费者",resource));
t1.start();
Thread t2 = new Thread(new MyThread("生产者",resource));
t2.start();
}
}
}
需要注意的几点是
1. 要在synchronized的函数或对象里使用wait、notify和notifyAll,不然Java虚拟机会生成 IllegalMonitorStateException。
2. 要在while循环里而不是if语句下使用wait。这样,循环会在线程睡眠前后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知。
3. 要在多线程间共享的对象(在生产者消费者模型里即缓冲区队列)上使用wait。

本文深入探讨了生产者-消费者模型,这是多线程环境中关键的同步模式。通过一个具体的Java实现案例,展示了如何利用wait和notify机制来确保线程间的正确同步,避免数据竞争和死锁。文章强调了在synchronized上下文中使用这些方法的重要性,以及在循环中检查条件以防止虚假唤醒。
252

被折叠的 条评论
为什么被折叠?



