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

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


需要注意的是

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的锁资源,直到退出synchronized
						System.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;
		}

		@Override
		public 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;
		}

		@Override
		public void run() {
			System.out.println(Thread.currentThread().getName()
					+ " consumer get:" + num);
			// 开始消费
			wareHouse.get(num);

		}

	}

	public void test() {
		// 初始化一个仓库,仓库当前物品数为0,仓库容量为100
		WareHouse 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值