java线程模拟生产者消费者问题
发布日期:2021-06-30 17:51:03 浏览次数:4 分类:技术文章

本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:synchronized(class)、synchronized(this)与synchronized(object)的区别分析
下一篇:线程同步问题分析

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月22日 07时26分32秒