多线程——生产者与消费者(多)问题解决

package 多线程;

public class PandC {

	public static void main(String[] args) {
//		Producer p= new Producer();
//		Consumer c = new Consumer();
//		new Thread(p,"生产者").start();
//		new Thread(p,"生产者").start();
//		new Thread(c,"消费者").start();
//		new Thread(c,"消费者").start();
		new Thread(new Producer(),"生产者").start();
		new Thread(new Consumer(),"消费者").start();
		new Thread(new Producer(),"生产者").start();
		new Thread(new Consumer(),"消费者").start();
	}
}
//通过单例模式 保证资源唯一
//class Resource{
//	private String name;
//	private int count;
//	private boolean flag=false;
//	static Resource r = new Resource();
//	private Resource() {
//	}
//	public static Resource getRes(){
//		return r;
//	}
//	public synchronized void produce(String name){
//		if(!flag)
//			try {
//				wait();//this.wait(); //this可省略
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//		name = name+count++;
//		flag=false;
//		System.out.println(Thread.currentThread().getName()+" .........生产商品:"+count);
//		this.notify();//this可省略
//	}
//	public synchronized void consume(){
//		if(flag)
//			try {
//				wait();
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//		flag=true;
//		System.out.println(Thread.currentThread().getName()+" ======消费商品:"+count);
//		notify();
//	}
//}
class Producer implements Runnable{
	Resource r = Resource.getRes();
	@Override
	public void run() {
		while(true)
			r.produce("商品:");
	}
}
class Consumer implements Runnable{
	Resource r = Resource.getRes();
	@Override
	public void run() {
		while(true)
			r.consume();
	}
}

/*
 输出:     				生产一个   被消费两次
 生产者 .........生产商品:44500
消费者 ======消费商品:44500
消费者 ======消费商品:44500
生产者 .........生产商品:44501
消费者 ======消费商品:44501
消费者 ======消费商品:44501
					生产两个  却只被消费一个
生产者 .........生产商品:45841
生产者 .........生产商品:45842
消费者 ======消费商品:45842
生产者 .........生产商品:45843
消费者 ======消费商品:45843
 * 
 解决办法   每次线程被唤醒 都去判断一次flag  并 需要唤醒所有线程 否则会出现所有线程全部等待
 代码:*/
 class Resource{
	private String name;
	private int count;
	private boolean flag=false;
	static Resource r = new Resource();
	private Resource() {
	}
	public static Resource getRes(){
		return r;
	}
	public synchronized void produce(String name){
		while(!flag)
			try {
				wait();//this.wait(); //this可省略
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		name = name+count++;
		flag=false;
		System.out.println(Thread.currentThread().getName()+" .........生产商品:"+count);
		this.notifyAll();//this可省略
	}
	public synchronized void consume(){
		while(flag)
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		flag=true;
		System.out.println(Thread.currentThread().getName()+" ======消费商品:"+count);
		notifyAll();
	}
}

对于多个生产者和消费者

为什么要定义while判断标记??

原因:让被唤醒的线程,再一次判断标记

为什么定义notifyAll

原因:要唤醒对方线程,要唤醒对方线程只能通过唤醒同一锁上的所有线程

如果值用notify的话,容易出现唤醒本方线程的情况,导致两方线程都处于等待中

时间: 2024-10-31 03:24:39

多线程——生产者与消费者(多)问题解决的相关文章

JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题

JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序员杜鹏程的博客:http://blog.csdn.net/m366917 我们来继续学习多线程 Lock锁的使用 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock Lock void lock():获取锁 v

多线程-生产者与消费者(存储数据与打印数据)

无线程同步: 存储数据: 1 public class Storage { 2 int data; 3 4 public int getData() { 5 return data; 6 } 7 8 public void setData(int data) { 9 this.data = data; 10 } 11 12 } 产生数据: 1 public class Counter implements Runnable { 2 private Storage storage; 3 4 pub

Java多线程--生产者与消费者问题

说明 Java中,线程之间的通信主要是由java.lang.Object类提供的wait.notify和notifyAll这3个方法来完成: ①对象的wait方法被调用后,线程进入对象的等待队列中,并释放对象锁,其它线程可以竞争使用此对象锁:sleep方法使得一个线程进入睡眠状态,但是线程所占有的资源并没有释放. ②当对象的notify方法被调用,该方法会从对象的等待队列中随机取出一个线程来唤醒:notifyAll是唤醒等待队列中所有线程,这些线程会与其它正在执行的线程共同竞争对象锁. ③wai

多线程——生产者和消费者的问题

生产者和消费者问题的产生 生产者和消费者是指俩个不同的线程对象,操作统一资源的情况:生产者负责生产数据,消费者负责消费数据,生产者每生产完一组数据后,消费者  消费一组数据, Object对多线程的支持:  wait();等待被唤醒  notify();唤醒  notifyAll();唤醒所有 sleep()和wait()的区别: sleep()属于Thread类,类似于一个闹钟,只持续一定时间.wait()属于Object类,需要被notify()唤醒,如果不唤醒就会一直等待下去 具体案例如下

多线程生产者、消费者模式中,如何停止消费者?多生产者情况下对“毒丸”策略的应用。

生产者.消费者模式是多线程中的经典问题.通过中间的缓冲队列,使得生产者和消费者的速度可以相互调节. 对于比较常见的单生产者.多消费者的情况,主要有以下两种策略: 通过volatile boolean producerDone =false 来标示是否完成.生产者结束后标示为true, 消费者轮询这个变量来决定自己是否退出. 这种方式对producerDone产生比较大的争用,实现起来也有诸多问题需要考虑. 比较经典的"毒丸"策略,生产者结束后,把一个特别的对象:"毒丸&quo

2015阿里巴巴校招附加题:多线程-生产者和消费者

今天参加了阿里2015校招实习生的笔试. 选择题部分确实有水平,由于基础一般再加上没做准备,打得一塌糊涂,目测已经阵亡了,不过附加题的最后一个还是很基础的,关于java的多线程中的生产者和消费者的问题,在此感谢@绝影. 题目: 有个篮子,一个人不停地往里面放苹果,另一个不停地从里面拿出来苹果,篮子最多能放5个苹果,苹果数量无限.用Java模拟实现. 实现过程: 主类: class ProducerConsumer { public static void main(String[] args)

多线程——生产者和消费者(四)

通过前面三篇博客的介绍,基本上对Java的多线程有了一定的了解了,然后这篇博客根据生产者和消费者的模型来介绍Java多线程的一些其他知识. 我们这里的生产者和消费者模型为: 生产者Producer 生产某个对象(共享资源),放在缓冲池中,然后消费者从缓冲池中取出这个对象.也就是生产者生产一个,消费者取出一个.这样进行循环.   第一步:我们先创建共享资源的类 Person,它有两个方法,一个生产对象,一个消费对象 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

7.2.6 - 并发多线程 生产者,消费者

一 生产者消费者模型介绍 为什么要使用生产者消费者模型 生产者指的是生产数据的任务,消费者指的是处理数据的任务,在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这个问题于是引入了生产者和消费者模式. 什么是生产者和消费者模式 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生

多线程——生产者与消费者(多)1.5新锁,问题解决

package 多线程; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class PandCnewLock { public static void main(String[] args) { // Producer p= new Producer2(); //