1 总结:
* 对于线程死锁,用生产消费者模式|方案来解决, 生活中,人车 共用车道资源也是生产者消费者现象 * 生产者消费者模式有两种解决方式: * 1 用容器,容器满了 就停止 2 信号灯法,标识位 (这种方式下,必须要 this.wait() + this.notify() + synchronized 才生效)
1.1 对比 线程 多线程同步加锁说明 中的代码Web12306
这个类中是在真正线程类中的方法上增加锁,同时这个线程类里持有公共资源 tickets,然后多个线程代理类在不停的引用这个真正的线程类并调用真正线程类的方法来消费公共持有的 tickets
而2.1中的生产者消费者,是真正线程类中持有共同的业务bean,然后在业务bean的方法中增加锁,然后
类Producer和Consumer共同持有moive这个公共对象类,但是分别调用这个moive类的生产和消费方法。
注意区别
2.1 信号灯模式代码:
public class ProduceConsumeThread { /** * 对于线程死锁,用生产消费者模式|方案来解决, 生活中,人车 共用车道资源也是生产者消费者现象 * 生产者消费者模式有两种解决方式: * 1 用容器,容器满了 就停止 2 信号灯法,标识位 (这种方式下,必须要 this.wait() + this.notify() + synchronized 才生效) */ public static void main(String[] args) { Moive moive = new Moive(); // 多线程必须是对同一个对象moive的引用才能会在 moive方法中的 this.wait() this.notify()生效 new Thread(new Producer(moive),"电影院1").start();// 类Producer和Consumer共同持有moive这个公共对象类,但是分别调用这个moive类的生产和消费方法。 new Thread(new Consumer(moive),"张三").start();// 而在公共持有类moive的生产和消费这两个方法中,使用信号灯来控制对方的等待和执行 } } class Producer implements Runnable{ private Moive moive; public Producer() { } public Producer(Moive moive) { this.moive = moive; } @Override public void run() { for(int i=0; i<20; i++) { if(i%2 == 0) { moive.play("天空电影"); }else{ moive.play("草地电影"); } } } } class Consumer implements Runnable{ private Moive moive; // 公共持有类, 此类上持有业务方法 public Consumer() { } public Consumer(Moive moive) { this.moive = moive; } @Override public void run() { for(int i=0; i<20; i++) { moive.watch(); } } } class Moive{ private String msg ; // flag=true时, 生产者生产,消费者等待,生产完毕后通知消费者 // flag=false时,生产者等待,消费者消费,消费完毕后通知生产者 private boolean flag = true; // 生产 public synchronized void play(String msg) { if(!flag) {// 等待消费 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 开始生产 try { Thread.sleep(1000);// 模拟生产数据的耗时 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +" 生产了: " + msg); this.msg = msg; // 通知消费 this.notify(); this.flag = false; } // 消费 public synchronized void watch() { if(flag) {// 等待生产 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 开始消费 try { Thread.sleep(1000);// 模拟消费数据的耗时 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"消费了: " + msg); // 通知消费 this.notify(); this.flag = true; } }