三. 生产者和消费者同步 第二版
将上面的程序进行改写。
三.一 同步产品类 Info
里面有两个同步的方法。
public class Info { private String name; private String content; public Info(){ } //设置产品 public synchronized void setInfo(String name,String content){ this.setName(name); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } this.setContent(content); } //取出产品 public synchronized void getInfo(){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.getName()+"---->"+this.getContent()); } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getContent() { return this.content; } public void setContent(String content) { this.content = content; } }
三.二 生产者 Productor
public class Productor implements Runnable { private Info info=null; private boolean isFirst=true; public Productor(Info info){ this.info=info; } @Override public void run() { for(int i=0;i<50;i++){ System.out.println("输出 i:"+i+",isFirst:"+isFirst); if(isFirst){ //是第一个,那么就生产第一个消息 this.info.setInfo("两个蝴蝶飞","这是两个蝴蝶飞"); isFirst=false; }else{ this.info.setInfo("老蝴蝶","这是老蝴蝶"); isFirst=true; } } } }
三.三 消费者 Consumer
public class Consumer implements Runnable { private Info info=null; public Consumer(Info info){ this.info=info; } @Override public void run() { for(int i=0;i<50;i++){ System.out.println(""); //获取信息 this.info.getInfo(); } } }
三.四 主程序测试Demo
public class Demo { public static void main(String[] args) { //定义生产者 Info info=new Info(); //生产 Productor productor=new Productor(info); //消费 Consumer consumer=new Consumer(info); Thread thread=new Thread(productor); Thread thread1=new Thread(consumer); //启动 thread.start(); thread1.start(); } }
三.五 测试运行,发现问题
常常会先生产这一部分,后生产那一部分, 并不是生产一个,拿一个。
需要用 Object 对象的 wait() 和 notify(), notifyAll() 方法进行设置。
四. 等待和唤醒 生产者和消费者第三版
在Info 对象里面设置一个标识位, 如果生产了一件产品,那么就生产者先等待,让消费者去消费好之后,再重新生产,避免多次生产一件产品。
四.一 等待和唤醒 Info
package com.yjl.thread.cp.c3; /** * package: com.yjl.thread.cp * className: Info * Description: 请输入相应的描述 * * @author : yuezl * @Date :2020/6/13 12:53 */ public class Info { private String name; private String content; //定义标识位 private boolean flag=false; public Info(){ } public synchronized void setInfo(String name,String content){ if(flag){ //为真 try { super.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.setName(name); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } this.setContent(content); flag=true; //当前只有一个线程,唤醒一个线程, 也可以直接唤醒多个。 super.notifyAll(); } public synchronized void getInfo(){ if(!flag){ try { super.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.getName()+"---->"+this.getContent()); flag=false; //当前只有一个线程,唤醒一个线程, 也可以直接唤醒多个 super.notifyAll(); } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getContent() { return this.content; } public void setContent(String content) { this.content = content; } }
生产者,消费者和 Demo 均与 第二版的内容一样。
运行程序,控制台打印输出
发现,可以做到每次生产一个产品,取出一个产品的功能了。
但是,这种情况下,只有一个生产者和一个消费者,如果都有两个呢?
其实,我们可以先创建一个仓库, 当生产时,可以将产品放置到仓库里面, 当仓库满时,才不让继续生产, 如果仓库没有满,就继续生产。 当仓库没有产品时,就不让继续消费了。