1 package day2_4; 2 3 /** 4 * 线程通信的应用 经典例题: 生产者/消费者问题 5 * <p> 6 * 生产者(Productor)将产品交给店员(Clerk),而消费者(Consumer)从店员处取走产品, 7 * 店员一次只能持有固定数量范围的产品(比如 1-20个) 8 * 如果生产者试图生产更多的产品,店员会叫生产者停一下,等店中有空位放产品了再通知生产者继续生产。 9 * 如果店中没有产品了,店员会告诉消费者等一下,等店中有产品了再通知消费者来取走产品 10 * <p> 11 * 分析: 12 * 1.是否是多线程问题? 是 生产者线程、消费者线程 13 * 2.是否有共享数据? 是 店员(或产品) 14 * 3.如何解决线程的安全问题? 同步机制,有三种方法 15 * 4.是否涉及线程通信? 是 16 * 17 * @Author Tianhao 18 * @create 2021-02-05-23:42 19 */ 20 21 //店员 22 class Clerk { 23 //产品数量 24 private int productCount; 25 26 public Clerk(int productCount) { 27 this.productCount = productCount; 28 } 29 30 //生产产品 31 public synchronized void produceProduct() { 32 33 if (productCount < 20) { 34 productCount++; 35 System.out.println(Thread.currentThread().getName() + "成产了第" 36 + productCount + "个产品"); 37 //每生产了一个产品,就唤醒wait中的消费者 38 notify(); 39 40 } else { 41 try { 42 //等待 43 wait(); 44 } catch (InterruptedException e) { 45 e.printStackTrace(); 46 } 47 } 48 } 49 50 //消费产品 51 public synchronized void customProduct() { 52 if (productCount > 0) { 53 System.out.println(Thread.currentThread().getName() + "消费了第" 54 + productCount + "个产品"); 55 productCount--; 56 //每消费了一个产品,就唤醒正在wait的生产者 57 notify(); 58 } else { 59 try { 60 //等待 61 wait(); 62 } catch (InterruptedException e) { 63 e.printStackTrace(); 64 } 65 } 66 } 67 } 68 69 70 //生产者 71 class Productor extends Thread{ 72 private Clerk clerk; 73 74 public Productor(Clerk clerk) { 75 this.clerk = clerk; 76 } 77 78 @Override 79 public void run() { 80 System.out.println("生产者开始生产产品..."); 81 while (true) { 82 try { 83 Thread.sleep(10); 84 } catch (InterruptedException e) { 85 e.printStackTrace(); 86 } 87 clerk.produceProduct(); 88 } 89 } 90 } 91 92 //消费者 93 class Consumer extends Thread{ 94 private Clerk clerk; 95 96 public Consumer(Clerk clerk) { 97 this.clerk = clerk; 98 } 99 100 @Override 101 public void run() { 102 System.out.println("消费者开始消费产品..."); 103 while (true) { 104 try { 105 Thread.sleep(20); 106 } catch (InterruptedException e) { 107 e.printStackTrace(); 108 } 109 clerk.customProduct(); 110 } 111 } 112 } 113 114 public class ProductTest { 115 public static void main(String[] args) { 116 Clerk clerk = new Clerk(0); 117 Productor p = new Productor(clerk); 118 Consumer c = new Consumer(clerk); 119 Consumer c2 = new Consumer(clerk); 120 p.setName("生产者1"); 121 c.setName("消费者1"); 122 c2.setName("消费者2"); 123 p.start(); 124 c.start(); 125 c2.start(); 126 127 } 128 129 }