本示例实现生产者和消费者是用wait()和notifyAll()方法,这两个方法的使用比之前的suspend()和resume()方法的优势是
在synchronized方法包围的时候会释放锁,不会造成死锁。
缺点如果在一个方法中先执行notifyAll(),再执行wait()还是会造成死锁。
import java.util.*;
public class ThreadCommunication {
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
Provider provider = new Provider(5, queue);
Provider provider2 = new Provider(5, queue);
Consumer consumer = new Consumer(5, queue);
Consumer consumer2 = new Consumer(5, queue);
new Thread(provider).start();
new Thread(provider2).start();
new Thread(consumer).start();
new Thread(consumer2).start();
//改进可以使用线程池
}
}
//生产者线程(苹果放篮子)
class Provider implements Runnable {
private Queue<Integer> queue ;//存储队列相当于篮子
private Random ran = new Random(100);
private int boxSize;//设置篮子存储苹果的容量
public Provider(int boxSize,Queue<Integer> queue){
this.boxSize = boxSize;
this.queue = queue;
}
@Override
public void run() {
//需要线程循环跑
while (true) {
try { //减速线程跑的速度
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//wait方法和notify、notifyALl方法是基于监听方式的,必须要在方法外面加synchronized包住不然会报错
synchronized (queue) {
while (queue.size() == boxSize){//这里必须用循环判断,不能用if,因为程序存在着一种叫伪唤醒用if就会出问题
try {
System.out.println("生产者等待。。。。。");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int apple = ran.nextInt();
System.out.println("生产一个苹果" + apple);
queue.add(apple);
queue.notifyAll();
}
}
}
}
//消费者线程(篮子里拿出苹果)
class Consumer implements Runnable {
private Queue<Integer> queue ;
private int boxSize;
public Consumer(int boxSize,Queue<Integer> queue){
this.boxSize = boxSize;
this.queue = queue;
}
@Override
public void run() {
while (true) {
try {
//减速线程跑的速度
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (queue) {
while (queue.isEmpty()){
try {
System.out.println("消费者等待。。。。。");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费一个苹果" + queue.remove());
queue.notifyAll();
}
}
}
}
09-21