一个老问题,一只水杯完成倒水,喝水的动作,保证每次都是先倒水在喝水,
这是一个典型的 生产者-消费者模型,如何解决这样的类型的问题,这就是线程同步下的调度问题
这个模式的难点在于线程间的调度,线程建调度的本质也就是线程状态的转换配合synchronized 同步关键字的使用
不同的代码上的使用同一个同步锁达到不同模块之间的协调
生产线程 执行搜先拿到锁,判断水杯是否有水,没有就生产以后发出信号水杯已有水唤醒消费线程去消费,有的话就阻塞,等待消费以后继续生产
消费线程 与生产线程相反
锁同步和阻塞概念:
1 同步的前提要首先拿到锁 只要是Object的派生类都可以作为锁,保证锁的唯一性也是同步的关键。
2 然后就是阻塞问题,wait 是锁的方法,wait导致线程阻塞的时候会释放锁,但是必须在synchronized 内部使用,wait 和 notify 是对应的 同一个锁的notify就可以唤醒一个通过锁wait 导致线程阻塞,如果同一个锁的wait导致了
多个线程的阻塞 notify的时候就会随即唤醒一个阻塞的线程 而 sleep 是Thread的方法,sleep导致线程阻塞的时候不会释放锁,当这个锁在其他同步方法就不能运行,因为sleep不释放锁,所以其他的代码快就无法同步方法,应为锁是同步的前提,sleep 是通过设置时间解除阻塞
这里
水杯的代码package produce_costomer;
public class Cuper { public static boolean isEmpty = true; public static Object lock = new Object(); public void produce() throws InterruptedException { synchronized (lock) { //每次执行生产的时候首先判断杯子是否有水,如果没有水就执行倒水动作,然后唤醒这个线程阻塞的消费动作, //如果有水就阻塞等待消费完以后唤醒继续生产 if (isEmpty) { System.out.println("生产一杯水.....等待消费"); isEmpty = false; lock.notify(); } else { System.out.println("等待消费阻塞中..."); lock.wait(); isEmpty = false; lock.notify(); } } } public void costomer() throws InterruptedException { synchronized (lock) { if (!isEmpty) { System.out.println("消费一杯水.....等待生产"); lock.notify(); isEmpty = true; } else { System.out.println("等待生产阻塞中..."); lock.wait(); lock.notify(); isEmpty = true; } } } }
生产线程package produce_costomer;
public class ProduceThread extends Thread { private Cuper cup; public Cuper getCup() { return cup; } public void setCup(Cuper cup) { this.cup = cup; } @Override public void run() { // TODO Auto-generated method stub try { for (int i = 0; i < 5; i++) { System.out.println("p" + i); cup.produce(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
消费线程package produce_costomer;
public class CustomerThread extends Thread { private Cuper cup; public Cuper getCup() { return cup; } public void setCup(Cuper cup) { this.cup = cup; } @Override public void run() { // TODO Auto-generated method stub try { for (int i = 0; i < 5; i++) { System.out.println("c" + i); cup.costomer(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
测试 package produce_costomer;
/** * @author ty93 * */ public class client { public static void main(String[] args) { Cuper cup = new Cuper(); CustomerThread ct = new CustomerThread(); ct.setCup(cup); ProduceThread pt = new ProduceThread(); pt.setCup(cup); pt.start(); ct.start(); } }