`
20386053
  • 浏览: 461659 次
文章分类
社区版块
存档分类
最新评论

Java并发编程学习笔记之十三:生产者—消费者模型(含代码)

 
阅读更多

转载请注明出处:http://blog.csdn.net/ns_code/article/details/17249321

生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。

这里实现如下情况的生产--消费模型:

生产者不断交替地生产两组数据“姓名--1 --> 内容--1”,“姓名--2--> 内容--2”,消费者不断交替地取得这两组数据,这里的姓名--1”和“姓名--2模拟为数据的名称,“内容--1 ”和“内容--2 ”模拟为数据的内容。

由于本程序中牵扯到线程运行的不确定性,因此可能会出现以下问题:

1、假设生产者线程刚向数据存储空间添加了数据的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程将把信息的名称和上一个信息的内容联系在一起;

2、生产者生产了若干次数据,消费者才开始取数据,或者是,消费者取完一次数据后,还没等生产者放入新的数据,又重复取出了已取过的数据。

问题1很明显要靠同步来解决,问题2则需要线程间通信,生产者线程放入数据后,通知消费者线程取出数据,消费者线程取出数据后,通知生产者线程生产数据,这里用wait/notify机制来实现。

详细的实现代码如下:

class Info{	// 定义信息类
	private String name = "name";//定义name属性,为了与下面set的name属性区别开
	private String content = "content" ;// 定义content属性,为了与下面set的content属性区别开
	private boolean flag = true ;	// 设置标志位,初始时先生产
	public synchronized void set(String name,String content){
		while(!flag){
			try{
				super.wait() ;
			}catch(InterruptedException e){
				e.printStackTrace() ;
			}
		}
		this.setName(name) ;	// 设置名称
		try{
			Thread.sleep(300) ;
		}catch(InterruptedException e){
			e.printStackTrace() ;
		}
		this.setContent(content) ;	// 设置内容
		flag  = false ;	// 改变标志位,表示可以取走
		super.notify();
	}
	public synchronized void get(){
		while(flag){
			try{
				super.wait() ;
			}catch(InterruptedException e){
				e.printStackTrace() ;
			}
		}
		try{
			Thread.sleep(300) ;
		}catch(InterruptedException e){
			e.printStackTrace() ;
		}
		System.out.println(this.getName() + 
			" --> " + this.getContent()) ;
		flag  = true ;	// 改变标志位,表示可以生产
		super.notify();
	}
	public void setName(String name){
		this.name = name ;
	}
	public void setContent(String content){
		this.content = content ;
	}
	public String getName(){
		return this.name ;
	}
	public String getContent(){
		return this.content ;
	}
}
class Producer implements Runnable{	// 通过Runnable实现多线程
	private Info info = null ;		// 保存Info引用
	public Producer(Info info){
		this.info = info ;
	}
	public void run(){
		boolean flag = true ;	// 定义标记位
		for(int i=0;i<10;i++){
			if(flag){
				this.info.set("姓名--1","内容--1") ;	// 设置名称
				flag = false ;
			}else{
				this.info.set("姓名--2","内容--2") ;	// 设置名称
				flag = true ;
			}
		}
	}
}
class Consumer implements Runnable{
	private Info info = null ;
	public Consumer(Info info){
		this.info = info ;
	}
	public void run(){
		for(int i=0;i<10;i++){
			this.info.get() ;
		}
	}
}
public class ThreadCaseDemo03{
	public static void main(String args[]){
		Info info = new Info();	// 实例化Info对象
		Producer pro = new Producer(info) ;	// 生产者
		Consumer con = new Consumer(info) ;	// 消费者
		new Thread(pro).start() ;
		//启动了生产者线程后,再启动消费者线程
		try{
			Thread.sleep(500) ;
		}catch(InterruptedException e){
			e.printStackTrace() ;
		}

		new Thread(con).start() ;
	}
}


执行结果如下:

另外,在run方法中,二者循环的次数要相同,否则,当一方的循环结束时,另一方的循环依然继续,它会阻塞在wait()方法处,而等不到对方的notify通知。

分享到:
评论

相关推荐

    Java并发编程学习笔记.rar

    这本"Java并发编程学习笔记"可能是作者在深入研究Java并发特性、工具和最佳实践过程中积累的心得体会。下面,我们将根据这个主题,探讨一些关键的Java并发编程知识点。 1. **线程与进程**:在多任务环境中,线程是...

    JUC并发编程学习笔记(硅谷)

    "JUC并发编程学习笔记(硅谷)"很可能包含了关于Java并发工具集(Java Util Concurrency, JUC)的深入理解和实战经验。JUC是Java标准库提供的一套强大的并发处理工具,它极大地简化了多线程编程,提高了程序的可读性...

    Java并发编程与高并发解决方案-学习笔记.pdf

    学习Java并发编程时,锁的概念是无法回避的。锁是同步的一种机制,用来控制多个线程访问共享资源的顺序。在Java中,锁主要有两种类型:内置锁和显示锁。内置锁使用synchronized关键字实现,而显示锁则是通过java....

    Java并发实践-学习笔记

    8. **并发设计模式**:笔记可能还会涉及一些经典的并发设计模式,如生产者-消费者模式、读写锁策略、双检锁/双重校验锁定(DCL)等。 9. **JVM内存模型**:Java内存模型(JMM)是理解并发行为的基础,笔记会解释其工作...

    Java线程编程学习笔记(二)

    这篇“Java线程编程学习笔记(二)”很可能是对Java并发编程深入探讨的一部分,特别是涉及多线程示例的实践应用。我们将从标题、描述以及标签来推测可能涵盖的知识点,并结合"Multi-Threads Demo"这一压缩包文件名来...

    Java 并发编程学习笔记之核心理论基础

    这些方法允许线程释放锁并等待其他线程的通知,是实现生产者消费者模式、哲学家就餐问题等经典并发模型的基础。 总结来说,Java并发编程的核心理论包括共享性、互斥性、线程间通信以及各种同步和并发工具的使用。...

    并发编程笔记+包含所有

    1. 生产者-消费者模式:通过队列进行通信,生产者将数据放入队列,消费者从队列中取出数据。 2. 线程池模式:通过预创建线程,避免频繁创建销毁线程的开销。 3. 双重检查锁定(Double-Checked Locking):确保单例...

    java并发笔记,包含线程池

    8. **并发模式**:包括生产者消费者模型、读者写者模型、菲尼克斯柱子(Fork/Join框架)等,这些都是解决并发问题的经典设计模式。 9. **并发异常处理**:线程间的异常处理需要注意,一旦一个线程抛出未捕获异常,...

    JAVA经典教材笔记

    - 生产者-消费者模型:使用阻塞队列实现。 - 生产者-消费者模型的优点:解耦生产者与消费者。 - **线程生命周期** - 线程的状态:NEW、RUNNABLE、BLOCKED等。 - 线程状态转换图。 #### 第十章:泛型 - **泛型...

    2022年Java学习笔记-Java课程配套案例.rar

    也可能包含多线程的实战,比如生产者消费者模型等。这些案例旨在帮助学习者通过实践加深理解,提高编程能力。建议按照案例的指导逐步学习,遇到问题时查阅相关文档或在线资源,以期全面掌握Java编程。

    JUC学习笔记(Java多线程)

    还有`BlockingQueue`,它是生产者-消费者模型的基础,如`ArrayBlockingQueue`、`LinkedBlockingQueue`等,它们在满时阻塞生产者,在空时阻塞消费者,确保了数据的一致性。 JUC还引入了`Semaphore`信号量,用于限制...

    java多线程学习笔记

    - **BlockingQueue**:队列接口,常用于生产者消费者模型,如ArrayBlockingQueue、LinkedBlockingQueue等。 - **CountDownLatch/CyclicBarrier/Semaphore**:高级并发工具类,用于协调多线程之间的协作。 5. **...

    concurrentTang:Java多线程高并发学习笔记代码

    "concurrentTang"项目显然是一个专注于Java多线程与高并发学习的资源集合,其中包含了作者的学习笔记和相关代码示例。通过这个项目,开发者可以深入理解并掌握Java在并发环境下的编程技巧。 Java多线程允许程序同时...

    java学习笔记

    掌握如何创建线程(通过Thread类或实现Runnable接口)、线程同步(synchronized关键字、wait()和notify()方法)、线程通信(如生产者消费者模型)以及线程池(ExecutorService)等,可以提高程序的并发性能。...

    java多线程笔记

    生产者消费者模型是常见的多线程协作模式,通过`BlockingQueue`等工具实现线程间的通信和同步。死锁是指两个或更多线程相互等待对方释放资源而无法继续执行的情况,应避免创建这样的循环等待。线程之间的数据传递...

    Go 学习笔记 第四版

    《Go学习笔记第四版》是一本深度探讨Go语言的书籍,专为想要深入理解Go语言特性和实战应用的读者设计。Go语言,又称Golang,是Google在2009年发布的一种静态类型、编译型、并发型且具有垃圾回收功能的编程语言。其...

    线程学习实例和笔记

    Java并发编程中常见的模型有生产者消费者模型、读者写者模型、哲学家就餐问题等。这些模型为解决特定的并发问题提供了理论基础。 五、源码分析 了解线程的工作原理,查看JVM和Java库的源码是非常有益的。例如,可以...

    java并发框架源码-notes:记录各种学习笔记(Java、算法、框架、数据库、并发、源码...)

    通过阅读和研究这些源码,开发者不仅可以提升对Java并发编程的理解,还能学习到如何在实际项目中应用这些知识,优化代码性能,解决并发问题。日常总结和记录这些知识点,是提升个人技术能力的有效途径。

    Java Concurrency In Practice Learning Note

    《Java并发编程实践》学习笔记 Java并发编程是Java开发者必须掌握的重要技能之一,尤其是在多核处理器和高并发系统的背景下,高效地管理线程和资源显得尤为重要。《Java Concurrency In Practice》一书深入浅出地...

    ejb 学习笔记5

    ### 深入解析《ejb学习笔记5》——消息驱动Bean详解 #### 消息驱动Bean概述 消息驱动Bean(MDB,Message Driven Bean)是Enterprise JavaBeans(EJB)框架中的一个重要组成部分,主要用于接收并处理来自消息中间件...

Global site tag (gtag.js) - Google Analytics