`
人生难得糊涂
  • 浏览: 117359 次
社区版块
存档分类
最新评论

JAVA线程消费者与生产者模型

 
阅读更多

    本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7433673,转载请注明。 

 

 

  上一篇讲述了线程的互斥(同步),但是在很多情况下,仅仅同步是不够的,还需要线程与线程协作(通信),生产者/消费者问题是一个经典的线程同步以及通信 的案例。该问题描述了两个共享固定大小缓冲区的线程,即所谓的“生产者”和“消费者”在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到 缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空 时消耗数据。要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往 缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者,通常采用线程间通信的方法解决该问题。如果 解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。

 

  假设有这样一种情况,有一个盘子,盘子里只能放一个鸡蛋,A线程专门往盘子里放鸡蛋,如果盘子里有鸡蛋,则一直等到盘子里没鸡蛋,B线程专门从盘子里取鸡 蛋,如果盘子里没鸡蛋,则一直等到盘子里有鸡蛋。这里盘子是一个互斥区,每次放鸡蛋是互斥的,每次取鸡蛋也是互斥的,A线程放鸡蛋,如果这时B线程要取鸡 蛋,由于A没有释放锁,B线程处于等待状态,进入阻塞队列,放鸡蛋之后,要通知B线程取鸡蛋,B线程进入就绪队列,反过来,B线程取鸡蛋,如果A线程要放 鸡蛋,由于B线程没有释放锁,A线程处于等待状态,进入阻塞队列,取鸡蛋之后,要通知A线程放鸡蛋,A线程进入就绪队列。我们希望当盘子里有鸡蛋时,A线 程阻塞,B线程就绪,盘子里没鸡蛋时,A线程就绪,B线程阻塞,代码如下:

 

import java.util.ArrayList;
import java.util.List;
/** 定义一个盘子类,可以放鸡蛋和取鸡蛋 */
public class Plate {
	/** 装鸡蛋的盘子 */
	List<Object> eggs = new ArrayList<Object>();
	/** 取鸡蛋 */
	public synchronized Object getEgg() {
		while (eggs.size() == 0) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		Object egg = eggs.get(0);
		eggs.clear();// 清空盘子
		notify();// 唤醒阻塞队列的某线程到就绪队列
		System.out.println("拿到鸡蛋");
		return egg;
	}
	/** 放鸡蛋 */
	public synchronized void putEgg(Object egg) {
		while (eggs.size() > 0) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		eggs.add(egg);// 往盘子里放鸡蛋
		notify();// 唤醒阻塞队列的某线程到就绪队列
		System.out.println("放入鸡蛋");
	}
	static class AddThread&nbsp;implements Runnable&nbsp; {
		private Plate plate;
		private Object egg = new Object();
		public AddThread(Plate plate) {
			this.plate = plate;
		}
		public void run() {
			plate.putEgg(egg);
		}
	}
	static class GetThread&nbsp;implements Runnable&nbsp; {
		private Plate plate;
		public GetThread(Plate plate) {
			this.plate = plate;
		}
		public void run() {
			plate.getEgg();
		}
	}
	public static void main(String args[]) {
		Plate plate = new Plate();
		for(int i = 0; i < 10; i++) {
			new Thread(new AddThread(plate)).start();
			new Thread(new GetThread(plate)).start();
		}
	}
}

 

 

 

  程序开始,A线程判断盘子是否为空,放入一个鸡蛋,并且唤醒在阻塞队列的一个线程,阻塞队列为空;假设CPU又调度了一个A线程,盘子非空,执行等待,这 个A线程进入阻塞队列;然后一个B线程执行,盘子非空,取走鸡蛋,并唤醒阻塞队列的A线程,A线程进入就绪队列,此时就绪队列就一个A线程,马上执行,放 入鸡蛋;如果再来A线程重复第一步,在来B线程重复第二步,整个过程就是生产者(A线程)生产鸡蛋,消费者(B线程)消费鸡蛋。

 

     大家注意到没有,在调用wait方法时,都是用while判断条件的,而不是if,在wait方法说明中,也推荐使用while,因为在某些特定的情况 下,线程有可能被假唤醒,使用while会循环检测更稳妥。wait和notify方法必须工作于synchronized内部,且这两个方法只能由锁对 象来调用。

分享到:
评论

相关推荐

    java多线程经典模型生产者消费者

    java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型...

    java实现多线程经典模型生产者消费

    java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现...

    Java 线程间通信,生产者与消费者模型

    使用wait()和notify()实现的生产者与消费者模型,可以了解如何使用wait()和notify()进行线程间通信。(上一次上传的代码有一个问题没有考虑到,这次修补了——CSDN没法撤销资源,只能再上传了)

    java多线程实现生产者和消费者

    9. **测试与调试**:多线程问题往往难以复现,因此在编写生产者-消费者代码时,应编写充分的测试用例,包括边界情况,如缓冲区满和空的状态转换。 通过理解和掌握这些知识点,开发者能够有效地实现生产者-消费者...

    Java多线程实现生产者消费者

    本示例中的“生产者-消费者”模型是一种经典的多线程问题,它模拟了实际生产环境中的资源分配与消耗过程。下面我们将详细探讨如何在Java中实现这个模型。 首先,我们要理解生产者-消费者模型的基本概念。在这个模型...

    java多线程_消费者与生产者模型

    在Java多线程编程中,消费者-生产者模型是一种经典的线程间通信模式,用于解决多线程环境下的数据共享问题。该模型涉及到两个主要的角色:生产者(Producer)和消费者(Consumer)。生产者负责创建数据,而消费者则...

    java线程安全以及生产者消费者demo

    Java线程安全与生产者消费者模型是多线程编程中的两个重要概念,它们在并发处理中扮演着关键角色。在Java中,线程安全是指一个类或者方法在多线程环境下能够正确地处理数据,避免数据的不一致性或竞态条件。而生产者...

    Java线程间的通信----生产者消费者模型

    生产者消费者模型是一种经典的线程同步问题,它模拟了实际生活中的生产过程和消费过程,使得生产者线程可以将数据生产出来,而消费者线程则负责消耗这些数据,两者之间通过共享数据结构进行协同工作。 生产者消费者...

    java 多线程生产者消费者模型demo

    Java多线程生产者消费者模型是一种典型的线程协作模式,用于解决并发编程中资源的高效利用和同步问题。在这个模型中,"生产者"线程负责生成数据,而"消费者"线程则负责处理这些数据。为了实现这种模式,Java提供了...

    java多线程(生产者与消费者)

    总结来说,“java多线程(生产者与消费者)”是关于如何在Java中使用同步、线程间通信和共享资源来实现高效且安全的并发编程。通过理解并熟练应用这些概念和工具,开发者可以构建出能够充分利用多核处理器能力的高...

    java多线程实现生产者消费者关系

    此外,`TestThread3.java`可能是测试此类模型的具体实现,它通常会创建多个生产者和消费者线程实例,并启动它们。每个线程会根据其角色调用相应的`produce()`或`consume()`方法。 在实际开发中,除了使用...

    java生产者消费者模型

    Java生产者消费者模型是多线程编程中一种经典的并发控制模型,它源于操作系统中的哲学思想,用于解决资源的共享和异步处理问题。在该模型中,"生产者"线程负责生成数据,而"消费者"线程则负责消费这些数据。两者之间...

    操作系统:多线程处理生产者消费者,java实现

    基本满足操作系统课上要求,java实现的生产者消费者模型。

    java线程实现的生产者和消费者的程序

    Java线程实现的生产者和消费者程序是一种经典的多线程设计模式,用于处理并发操作中的数据共享问题。这种模式在实际编程中广泛应用,特别是在需要高效处理数据流和资源管理的系统中。以下将详细讲解其核心概念、实现...

    由生产者/消费者问题看JAVA多线程

    ### 由生产者/消费者问题深入理解JAVA多线程 #### 生产者/消费者问题概述 生产者/消费者问题是一个经典的计算机科学问题,用于展示进程间的通信与同步问题。在这个模型中,生产者负责创建数据并将其放置到共享内存...

    生产者和消费者模式多线程

    生产者和消费者模式是多线程编程中一个经典的设计模式,它主要解决的是在多线程环境下资源的有效利用和同步问题。在这个模式中,生产者负责生成数据,而消费者负责消费这些数据。为了保证生产与消费的平衡以及避免...

    学习Java线程之并发协作生产者消费者模型.pdf

    Java线程中的并发协作模型是多线程编程中一个核心的概念,它主要通过生产者消费者模型来体现。在这个模型中,生产者线程负责创建或生产资源,而消费者线程则负责消耗这些资源。为了保证线程之间的协作和数据的一致性...

    多线程模拟实现生产者/消费者模型

    在给定的压缩包文件"生产者与消费者代码"中,很可能包含了实现这一模型的示例代码。通过阅读和分析这些代码,你可以更好地理解如何在实际项目中应用生产者/消费者模型。例如,你可能会看到如何创建线程,如何初始化...

    Java多线程 生产者-消费者模式

    Java多线程中的生产者-消费者模式是一种典型的同步与协作模型,它用于解决在多线程环境下资源的有效利用和协调问题。在这个模式中,通常有两个角色:生产者和消费者。生产者负责创建产品,而消费者则负责消费这些...

Global site tag (gtag.js) - Google Analytics