问题描述:生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
问题分析:
1.是否是多线程问题? 是,生产者线程,消费者线程
2.是否有共享数据? 是,店员(或产品)
3.如何解决线程的安全问题?同步机制,有三种方法
4.是否涉及到线程的通信? 是
代码实现:
方式一:采用继承Thread类,同步代码块的方式
class Clerk {//产品 //定义产品 private int productnum = 0; //生产产品 public synchronized void produceProduct() { if (productnum < 20) { productnum++; System.out.println(Thread.currentThread().getName() + "正在生产第" + productnum + "个产品。"); //唤醒对方 notify(); } else { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } //消费产品 public synchronized void consumeProduct() { if (productnum > 0) { System.out.println(Thread.currentThread().getName() + "正在消费第" + productnum + "个产品。"); productnum--; //唤醒对方 notify(); } else { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Producer extends Thread {//生产者 private Clerk clerk; public Producer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { System.out.println(Thread.currentThread().getName() + ":开始生产产品......"); while (true) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } clerk.produceProduct(); } } } class Consumer extends Thread { //消费者 private Clerk clerk; public Consumer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { System.out.println(Thread.currentThread().getName() + ":开始消费产品......"); while (true) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } clerk.consumeProduct(); } } } public class ProductTest { public static void main(String[] args) { Clerk clerk = new Clerk(); Producer p1 = new Producer(clerk); Consumer c1 = new Consumer(clerk); Consumer c2 = new Consumer(clerk); p1.setName("生产者1"); c1.setName("消费者1"); c2.setName("消费者2"); p1.start(); c1.start(); c2.start(); } }
方式二:采用实现Runnable接口、同步代码块的方式:
class Clerk1{ private int productcount = 0; public synchronized void creatProduct() { if (productcount < 20){ productcount++; System.out.println(Thread.currentThread().getName() + "正在生产第" + productcount + "个产品"); notify(); }else { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void reduceProduct() { if (productcount > 0){ System.out.println(Thread.currentThread().getName() + "正在消费第" + productcount + "个产品"); productcount--; notify(); }else { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Produce1 implements Runnable{ private Clerk1 clerk1; public Produce1(Clerk1 clerk1) { this.clerk1 = clerk1; } @Override public void run() { System.out.println(Thread.currentThread().getName() + "开始生产产品....."); while (true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } clerk1.creatProduct(); } } } class Consumer1 implements Runnable{ private Clerk1 clerk1; public Consumer1(Clerk1 clerk1) { this.clerk1 = clerk1; } @Override public void run() { System.out.println(Thread.currentThread().getName() + "开始消费产品......"); while (true){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } clerk1.reduceProduct(); } } } public class ProductTest1 { public static void main(String[] args) { Clerk1 clerk1 = new Clerk1(); Produce1 produce1 = new Produce1(clerk1); Consumer1 consumer1 = new Consumer1(clerk1); Thread t1 = new Thread(produce1); Thread t2 = new Thread(consumer1); Thread t3 = new Thread(consumer1); t1.setName("生产者1"); t2.setName("消费者1"); t3.setName("消费者2"); t1.start(); t2.start(); t3.start(); } }