在现实应用中,很多时候,都需要去控制多个线程按照一定的次序去访问同一个共享的资源,比如生产–消费的经典案例
Java中提供3个重要的方法解决线程间的通信问题,这三个方法分别是wait();notify();notifyAll();
下面是一个生产苹果和消费苹果的案例,每次放入篮子中5个苹果之后,再从篮子中一个个取出,再放入,再取出,依次循环4轮;
import java.util.LinkedList;
public class ProductConsumeDemo {
public static void main(String[] args) {
Basket basket = new Basket();
Productor productor = new Productor(basket);
productor.start();
Consumer consumer = new Consumer(basket);
consumer.start();
}
}
class Productor extends Thread{
private Basket basket=null;
public Productor(Basket basket) {
this.basket=basket;
}
@Override
public void run() {
basket.pushApple();
}
}
class Consumer extends Thread{
private Basket basket =null;
public Consumer(Basket basket){
super();
this.basket=basket;
}
@Override
public void run() {
basket.popApple();
}
}
//篮子
class Basket{
private LinkedList<Apple> basket = new LinkedList<>();
//放四轮苹果
public synchronized void pushApple(){
for (int i = 0; i < 20; i++) {
Apple apple = new Apple(i);
push(apple);
}
}
//取四轮苹果
public synchronized void popApple(){
for (int i = 0; i < 20; i++) {
pop();
}
}
//向篮子中放苹果,放5个,就通知消费者
private void push(Apple apple){
if (basket.size()==5) {
try {
wait();
//wait和sleep方法的区别就是wait需要调用notify或者notifyAll方法去唤醒
//sleep的话时间已过就会自动的醒来
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//等待并释放当前的锁
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
basket.addFirst(apple);
System.out.println("生产苹果:"+apple.toString());
notify();//通知消费者来消费
}
//从篮子中取苹果,如果篮子中苹果味0个,就通知生产者
private void pop(){
LinkedList<Apple> basket2 = basket;
if (basket2.size()==0) {
try {
wait();//等待生产者
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(500); //等待的时间
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Apple apple = basket.removeFirst();
System.out.println("吃掉苹果:"+apple.toString());
notify(); //通知生产者来生产
}
}
//苹果类
class Apple{
private int id;
public Apple(int id){
this.id = id;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "苹果"+(id+1);
}
}