java同步互斥,生产者消费者

来源:互联网 发布:淘宝卖家更改类目 编辑:程序博客网 时间:2024/06/11 18:54

下面的例子模拟了一个生产者消费者的同步场景,在生产者生产的时候加入了仓库的容量和当前放置数的比较,注释写的很清楚,有问题请留言


需要注意的是

1.wait方法会释放当前同步块的锁,

2.notifyAll   wait  notify方法都要在同步块或者方法中调用

3.notifyAll   只是唤醒所有在锁上等待的线程,但是这些线程被唤醒后也会去竞争锁,只有一个线程能拿到锁,知道这个线程退出同步块,其他线程才能继续拿到锁运行,如此往复,可参考http://zhidao.baidu.com/link?url=F5NOESI9MbShg90JTHRthubuQVaeu7QksUwzGYUzWy-H0ePlu5uWs9_DYkDXJngggeT3A2wrE4GpbFZINqPAttKbGgGoTORKNsI87G4IFLC



public class ThreadTest {String flag = "flag";/** * 仓库 *  * @author jinjing *  */class WareHouse {private int num;private int max_num = 100;public WareHouse(int num, int max_num) {this.num = num;this.max_num = max_num;}public void add(int number) {// 如果要生产的数量大于仓库的容量则直接退出if (number > max_num) {System.out.println("number is too big");return;}synchronized (flag) {// 相加大于仓库的容量则等待10秒钟if ((num + number) > max_num) {System.out.println(Thread.currentThread().getName()+ " wait for get");try {this.wait(1000);} catch (Exception e) {e.printStackTrace();}}// 如果还大于仓库的容量则直接取消操作if ((num + number) > max_num) {System.out.println(Thread.currentThread().getName()+ " add cancel warehouse have " + num);return;}// 仓库容量增加num = num + number;System.out.println(Thread.currentThread().getName()+ " sucess add " + number + " and warehouse have "+ num);// 唤醒所有在WareHouse实例上等待的线程,但是同一时刻只有一个线程拥有锁,直到拥有锁的线程退出synchronized块flag.notifyAll();}}public void get(int number) {if (number > max_num) {System.out.println("get number is too big");return;}// 获取锁,拿产品,若产品不够则等待synchronized (flag) {while ((num - number) < 0) {try {System.out.println(Thread.currentThread().getName()+ " " + System.currentTimeMillis()+ " wait for add");// 会释放flag的锁,其他线程将进来flag.wait();// notifyall唤醒所有线程,但是一个时刻只有一个线程拥有flag的锁资源,直到退出synchronizedSystem.out.println("awake "+ System.currentTimeMillis() + ":"+ Thread.currentThread().getName()+ "  now num-number=" + (num - number));} catch (Exception e) {e.printStackTrace();}}try {System.out.println(System.currentTimeMillis() + ":"+ Thread.currentThread().getName());Thread.sleep(3000);} catch (Exception e) {e.printStackTrace();}// 拿产品num = num - number;System.out.println(Thread.currentThread().getName()+ " sucess get " + number + " and warehouse have "+ num);// 唤醒所有在WareHouse实例上等待的线程flag.notifyAll();}}}/** * 生产者 *  * @author jinjing *  */class Producter implements Runnable {int num;WareHouse wareHouse;public Producter(int num, WareHouse wareHouse) {this.num = num;this.wareHouse = wareHouse;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+ " producter add:" + num);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 开始生产wareHouse.add(num);}}/** * 消费者 *  * @author jinjing *  */class Consumer implements Runnable {private volatile int num = 0;WareHouse wareHouse;public Consumer(int num, WareHouse wareHouse) {this.num = num;this.wareHouse = wareHouse;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+ " consumer get:" + num);// 开始消费wareHouse.get(num);}}public void test() {// 初始化一个仓库,仓库当前物品数为0,仓库容量为100WareHouse wareHouse = new WareHouse(0, 100);// 一个消费者,需要取10个货物Consumer consumer = new Consumer(10, wareHouse);// 一个生产者,需要放30个货物Producter producter = new Producter(10, wareHouse);// 一个生产者,需要放100个货物// Producter producter1 = new Producter(10, wareHouse);Thread t1 = new Thread(consumer);Thread t2 = new Thread(producter);Thread t3 = new Thread(consumer);Thread t4 = new Thread(producter);Thread t5 = new Thread(consumer);t1.start();t2.start();t3.start();t4.start();t5.start();}public static void main(String[] args) {ThreadTest threadTest = new ThreadTest();threadTest.test();}}


0 0