java线程模拟生产者消费者问题
发布日期:2021-06-30 17:51:03
浏览次数:5
分类:技术文章
本文共 4177 字,大约阅读时间需要 13 分钟。
所谓的生产者消费者问题,就是存在生产者和消费者两个线程,当仓库还没满的时候,生产者可以生产,当仓库没空的时候,消费者可以取走商品。
我们用实例说话:
下面,我们创建几个类:
1、消费者--主要负责消费商品
2、生产者--负责生产商品
3、仓库--存储商品,用一个变量表示仓库里面商品的数量。
首先,我们先用一个程序来引出我们的话题:
package com.huai.test;public class CPThreadTest { public static void main(String[] args) { Customer c = new Customer(); Product p = new Product(); Thread tc = new Thread(c); Thread tp = new Thread(p); tc.start(); tp.start(); }}class Customer implements Runnable { public void doConsume() { if (!Ware.isEmpty()) { Ware.productCount--; System.out.println("consume one, left " + Ware.productCount); } } @Override public void run() { while (true) { doConsume(); } }}class Product implements Runnable { public void doProduct() { if (!Ware.isFull()) { Ware.productCount++; System.out.println("product one, left " + Ware.productCount); } } @Override public void run() { while (true) { doProduct(); } }}class Ware { public static int productCount = 0; public static int max = 100; public static boolean isFull() { return productCount >= max; } public static boolean isEmpty() { return productCount <= 0; }}运行结果是:运行结果非常奇怪:从下面看出,消费者消费之后,仓库里面没有产品了,可是生产者竟然说还剩下100个。为什么会出现这么奇怪的现象呢?多线程共享相同数据造成的。为了避免这样的问题,我们应该怎么改进我们的程序呢?请看下面:
解决方案1:
思路:把Ware这个资源(这里我把Ware类称为资源)实现同步互斥。当生产者获得仓库的钥匙的时候,消费者就不能进去取走商品了,反之,当消费者获得仓库的钥匙正在消费商品的时候,生产者就不能生产并存入商品了。
package com.huai.test;public class CPThreadTest { public static void main(String[] args) { Customer c = new Customer(); Product p = new Product(); Thread tc = new Thread(c); Thread tp = new Thread(p); tc.start(); tp.start(); }}class Customer implements Runnable{ public void doConsume(){ synchronized (Ware.class) { if(!Ware.isEmpty()){ Ware.productCount--; System.out.println("consume one, left "+Ware.productCount); } } } @Override public void run() { while(true){ doConsume(); } }}class Product implements Runnable{ public void doProduct(){ synchronized (Ware.class) { if(!Ware.isFull()){ Ware.productCount++; System.out.println("product one, left "+Ware.productCount); } } } @Override public void run() { while(true){ doProduct(); } }}class Ware{ public static int productCount = 0; public static int max = 100; public static boolean isFull(){ return productCount >= max; } public static boolean isEmpty(){ return productCount <= 0; } }
部分运行结果:
consume one, left 22consume one, left 21consume one, left 20consume one, left 19consume one, left 18consume one, left 17consume one, left 16consume one, left 15consume one, left 14consume one, left 13consume one, left 12consume one, left 11consume one, left 10consume one, left 9consume one, left 8consume one, left 7consume one, left 6consume one, left 5consume one, left 4consume one, left 3consume one, left 2consume one, left 1consume one, left 0product one, left 1product one, left 2product one, left 3product one, left 4product one, left 5product one, left 6product one, left 7product one, left 8product one, left 9product one, left 10product one, left 11product one, left 12
解决方案2:
思路:把生产和消费这两个动作放到仓库里面,原理和上面的差不多,只是同步互斥的方式不一样。
注:在Ware中,当有一个线程正在运行synchronized方法的时候,其他申明了synchronized的方法也不能被其他线程访问,但可以访问非synchronized申明的方法。怎么验证?你可以把下面例子中的一个synchronized去掉,就会发现打印出来的结果,相邻两个的数字相差不全是1.
package com.huai.test;public class CPThreadTest { public static void main(String[] args) { Customer c = new Customer(); Product p = new Product(); Thread tc = new Thread(c); Thread tp = new Thread(p); tc.start(); tp.start(); }}class Customer implements Runnable { @Override public void run() { while (true) { Ware.doConsume(); } }}class Product implements Runnable { @Override public void run() { while (true) { Ware.doProduct(); } }}class Ware { public static int productCount = 0; public static int max = 100; public static boolean isFull() { return productCount >= max; } public static boolean isEmpty() { return productCount <= 0; } public static synchronized void doProduct(){ if (!Ware.isFull()) { Ware.productCount++; System.out.println("product one, left " + Ware.productCount); } } public static synchronized void doConsume(){ if (!Ware.isEmpty()) { Ware.productCount--; System.out.println("consume one, left " + Ware.productCount); } }}
转载地址:https://liangyihuai.blog.csdn.net/article/details/48969803 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
不错!
[***.144.177.141]2024年04月21日 05时54分09秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
ACM路上的一大失误
2019-04-30
HDOJ2049 不容易系列之(4)——考新郎
2019-04-30
CodeForces 248B - Chilly Willy - 找规律
2019-04-30
POJ-2418 Hardwood Species(Trie树)(map)
2019-04-30
HDU-4300 Clairewd’s message + 4333(扩展KMP)
2019-04-30
HDU 1592 Half of and a Half(高精度)
2019-04-30
POJ-3304 Segments(计算几何)
2019-04-30
UVA-11538 Chess Queen(数学)
2019-04-30
UVA-11401 Triangle Counting(数学优化)
2019-04-30
Codeforces Round #369 (Div. 2)
2019-04-30
UVA 11426 GCD - Extreme (II)(欧拉函数)
2019-04-30
HDU-2838 Cow Sorting(树状数组)
2019-04-30
POJ-2299 Ultra-QuickSort(树状数组)(离散化)
2019-04-30
基于SSM的兼职论坛系统的设计与实现
2019-04-30
基于java的图书管理系统的设计与实现
2019-04-30
基于java的SSM框架理财管理系统的设计与实现
2019-04-30
基于java的ssm框架就业信息管理系统的设计
2019-04-30
基于java的ssm框架的旅游网站设计与实现
2019-04-30