java基础-多线程等待唤醒机制(生产者和消费者)
·
生产者和消费者是一个非常经典的多线程协作的模式

第一种:消费者等待
1、消费者先看有没有需要执行的代码,如果没有就等待
2、等待的过程中,生产者就会去生产代码
3、生产完代码后,就会唤醒消费者执行代码
第二种:生产者等待
1、生产者判断是否有代码,如果有就等待
2、等待的过程中,消费者就会去执行代码
3、生产者判断如果没有代码,就会去生产
4、生产完成后就会去唤醒消费者执行代码


完成生产者和消费者(等待唤醒机制)的代码:实现线程轮流交替执行的效果
package Day15_thread;
public class Cook extends Thread {
@Override
public void run() {
//1、循环
//2、同步代码块
//3、判断共享数据是否到了末尾
//4、判断共享数据是否到了末尾,没有到末尾
while(true){
synchronized (Desk.lock){
//判断共享数据是否到了末尾
if(Desk.count==0){
break;
}else {
//1、判断桌子上是否有食物,如果有就等待
//2、如果没有食物,就生产
//3、生产完之后,就要修改桌子上食物的状态
//4、唤醒消费者
if(Desk.FoodFlag==1){
try {
Desk.lock.wait();//同样需要锁对象来调用wait,目的是绑定锁对象和线程
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}else {
//开始制作食物
System.out.println("生产者开始制作食物");
Desk.FoodFlag=1;
//唤醒消费者开吃
Desk.lock.notifyAll();
}
}
}
}
}
}
package Day15_thread;
public class Foodie extends Thread {
@Override
public void run() {
//1、循环
//2、同步代码块
//3、判断共享数据是否到了末尾
//4、判断共享数据是否到了末尾,没有到末尾
while(true){
synchronized (Desk.lock){
if(Desk.count==0){
break;
}else {
//先判断桌子上是否有实物
//如果没有就等待
//如果有就开吃
//吃完需要,唤醒生产者,还需要把吃的总数减一
//吃完之后需要修改桌子上食物FoodFlag的状态
if(Desk.FoodFlag==0){
//如果没有就等待,要用锁对象去调用wait方法
try {
Desk.lock.wait();//让当前进程和锁进行绑定
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}else {
//把吃的总数减一
Desk.count--;
//如果有就开吃
System.out.println("吃货在吃面条,还能吃"+Desk.count+"碗");
//吃完之后就要唤醒生产者
Desk.lock.notifyAll();
//修改桌子的状态
Desk.FoodFlag=0;
}
}
}
}
}
}
package Day15_thread;
public class Desk {
//控制生产者cook和消费者Foodis的执行
//用来描述是否有食物可以消费的一个标识
//0:没有食物,1:有食物
public static int FoodFlag=0;
//总个数:标识消费者最多能消费的最大数量
public static int count=10;
//锁对象
public static Object lock=new Object();
}
package Day15_thread;
public class ThreadTest01 {
public static void main(String[] args) {
Cook cook = new Cook();
Foodie foodie = new Foodie();
//给线程设置名字
cook.setName("生产者");
foodie.setName("消费者");
//开启线程
cook.start();
foodie.start();
}
}

等待唤醒机制的第二种实现方式:阻塞队列的方式实现


package Day15_thread;
import java.util.concurrent.ArrayBlockingQueue;
public class CookBlock extends Thread {
ArrayBlockingQueue<String> queue;
public CookBlock(ArrayBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
//不断的把食物放到阻塞队列中
try {
queue.put("食物");
System.out.println("生产者生产了食物");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
package Day15_thread;
import java.util.concurrent.ArrayBlockingQueue;
public class FoodieBlock extends Thread {
ArrayBlockingQueue<String> queue;
public FoodieBlock(ArrayBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
//不断的从阻塞队列中获取食物
try {
String take = queue.take();
System.out.println("消费者消费了"+take);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
package Day15_thread;
import java.util.concurrent.ArrayBlockingQueue;
public class ThreadTest02 {
public static void main(String[] args) {
//利用阻塞队列来完成生产者和消费者的代码
//细节:生产者和消费者必须使用同一个阻塞队列
//1、在测试类创建阻塞队列的对象
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(1);
CookBlock cookBlock = new CookBlock(queue);
FoodieBlock FoodieBlock = new FoodieBlock(queue);
cookBlock.start();
FoodieBlock.start();
}
}
这个打印内容看似有问题,实际上,是因为输出语句放在了锁外面导致的,不影响实际共享数据

线程的状态:


更多推荐




所有评论(0)