线程通信:
生产者和消费者之间的关系前面几期已经跟大家讲了,不懂生产者和消费者之间的关系可以去看我之前的文章,今天主要讲他们之间的线程通信
线程通信就是线程之间可以交流,你告诉我要干什么,我告诉你要干什么,有两个很重要的方法notify()和wait(),顾名思义一个通知,一个等待
那么为什么要线程通信呢,既然他们两个是互不影响的,因为可能出现逻辑错误,比如说生产者在生产者的时候,此时消费者应该在等待,不能够去消费,比如说你去买面包,但是此时第一批已经卖完了,此时你是不可以消费的,所以说如果你还在消费说明是不是逻辑错误了,这个时候老板通知面包师父去做,在告诉你等一会就可以买了,这不就是正常的逻辑嘛,这个过程发生了对话这就是通信
notify:
notify()方法是object类下的,源码我们可以看到它是一个被final和natice修饰的方法,没有方法体,在多线程中它是用来唤醒一个等待的线程
wait
wait()方法也是object类下的一个方法,被final修饰,没有被native修饰,
还抛出了中断异常,方法体调用了他的一个重载方法,wait()方法一共有三个重载方法,它在多线程中通常是用来让一个线程进入等待状态
接下来我们来写生产者与消费者通信代码
首先创建一个面包房类BreadRoom
package com.thread;
import java.util.Random;
/**
* @author 邓亚非
* 消费者来面包服买面包,如果面包服没有面包,面包房通知删除厂家去输出面包,然后通知消费者等待,等面包做好了
* 面包做好了,面包房通知消费者消费,此时生产者等待,
*/
public class BreadRoom {
Random random;
private String name;//面包服名称
private int count;
public BreadRoom(String name) {
this.name = name;
}
public synchronized void produce(BreadRoom breadRoom) {
System.out.println(breadRoom == this);
if (count == 0) {
System.out.println("生产者开始生产给" + breadRoom.name);
// 一次生产1-到30个
count = random.nextInt(29) + 1;
System.out.println("生产了" + count + "个面包");
}
// 此时通知消费者消费
breadRoom.notify();
// 消费者消费的时候生产者等待
try {
breadRoom.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 消费者消费方法
*
* @param breadRoom
*/
public synchronized void consume(BreadRoom breadRoom) {
System.out.println(breadRoom == this);
if (count == 0) {
// 面包数小于0,通知生产者生产
breadRoom.notify();
// 生产者在生产消费者等待
try {
breadRoom.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
// 面包树大于0消费者可以消费
System.out.println("消费者开始在" + breadRoom.name + "消费");
int sum = random.nextInt(count) + 1;
System.out.println("消费了" + sum + "个面包");
count -= sum;
System.out.println("面包还剩下" + count + "个");
}
}
}
创建生产者类Produce,需要依赖面包房类
package com.thread;
import com.sun.xml.internal.txw2.NamespaceResolver;
/**
* @author 邓亚非
* 生产者线程
*/
public class Produce extends Thread {
private BreadRoom breadRoom;
public Produce(BreadRoom breadRoom){
this.breadRoom= breadRoom;
}
/**
* 生产者线程体
*/
@Override
public void run() {
while (true){
breadRoom.produce(breadRoom);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
创建消费者类Consume,也要依赖面包房类
package com.thread;
/**
* @author 邓亚非
*/
public class Consume extends Thread{
private BreadRoom breadRoom;
public Consume(BreadRoom breadRoom){
this.breadRoom=breadRoom;
}
/**
* 消费者线程体
*/
@Override
public void run() {
breadRoom.consume(breadRoom);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}