当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

消费者与生产者

发表于: 2011-08-08   作者:dsr_22   来源:转载   浏览次数:
摘要: 多线程同步之生产者---消费者模型 线程同步是个老生常谈的问题了,在这里我将通过一个Java多线程程序,来说明控制相互交互的线程之间的运行进度,使程序运行总是既高效又稳定。这个多线程程序将采用生产者---消费者模型,来说明怎么样实现多线程的同步。 如果让我定义一下什么是消费者、生产者:我觉得可以把系统中使用某种资源的线程称为消费者,产生该种资源的线程称为生产者。在下面的Java的应用程序中,生

多线程同步之生产者---消费者模型

线程同步是个老生常谈的问题了,在这里我将通过一个Java多线程程序,来说明控制相互交互的线程之间的运行进度,使程序运行总是既高效又稳定。这个多线程程序将采用生产者---消费者模型,来说明怎么样实现多线程的同步。

如果让我定义一下什么是消费者、生产者:我觉得可以把系统中使用某种资源的线程称为消费者,产生该种资源的线程称为生产者。在下面的Java的应用程序中,生产者线程向一个线程安全的堆栈缓冲区中写(PUSH)数据,消费者从该堆栈缓冲区中读(POP)数据,这样,这个程序中同时运行的两个线程共享同一个堆栈缓冲区资源。

类Producer是生产者模型,其中的run方法中定义了生产者线程所做的操作,循环调用push()方法,将生产的100个字母送入堆栈中,每次执行完push操作后,调用sleep方法睡眠一段随机时间。

类Consumer是消费者模型,循环调用pop方法,从堆栈取出一个字母,一共取100次,每次执行完push操作后,调用sleep方法睡眠一段随机时间。

先看下同步堆栈类的源码:

 

package ProducerAndConsumer;

public class SyncStack {
	
	private int index = 0;
	private char[] data;
	private int size = 100;
	
	public SyncStack(int size){
		System.out.println("栈被创建");
		this.size = size;
		data = new char[size];
	}
	
	public synchronized void push(char c){
		while( index == size){
			try{
				System.out.println("栈满了!");
				this.wait();//等待,直到有数据出栈
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
		data[index] = c;
		index++;
		System.out.println("Produced:"+c);
		this.notify();//通知其它线程把数据出栈
	}
	
	public synchronized char pop(){
		while(index == 0){
			try{
				System.out.println("栈空了");
				this.wait();//等待其它线程把数据入栈
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
		index--;//指针向下移动
		char ch = data[index];
		System.out.println("Consumed:"+ch);
		this.notify();//通知其它线程把数据入栈
		return ch;
	}
	
	public synchronized void print(){
		for(int i=0; i<index; i++)
		{
			System.out.println(data[i]);
		}
		System.out.println();
		this.notify();//通知其它线程显示堆栈内容
	}
}

 

有了同步堆栈类,接着看看我们的生产者类的源码:

package ProducerAndConsumer;
public class Producer implements Runnable {
	private SyncStack theStack;

	public Producer(SyncStack s) {
		theStack = s;
	}

	public void run() {
        char ch;
        for(int i=0; i<100; i++){
        	//随机产生100个字符
        	ch = (char)(Math.random()*26 + 'A');
        	theStack.push(ch);
        	
        	try{
        		Thread.sleep((int)(Math.random()*1000));
        	}catch(InterruptedException e){
        		e.printStackTrace();
        	}
        }
	}
}

 

接着看下消费者类的源码:

package ProducerAndConsumer;

public class Consumer implements Runnable {
	private SyncStack theStack;
	
	public Consumer(SyncStack s){
		theStack = s;
	}

	public void run() {
		char ch;
		for(int i=0; i<100; i++){
			ch = theStack.pop();
		
		
		try{
			//每产生一个字符线程就睡眠一下
			Thread.sleep((int)(Math.random()*1000));
		}catch(InterruptedException e)
		{
			e.printStackTrace();
		}
		}
		
	}
	


}

 

最后让我们来看看主程序main所在类的源码:

package ProducerAndConsumer;

public class SyncTest {
public static void main(String[] args) {
	SyncStack stack = new SyncStack(5);
	Runnable source = new Producer(stack);
	Runnable sink = new Consumer(stack);
	
	Thread t1 = new Thread(source);
	Thread t2 = new Thread(sink);
	
	t1.start();
	t2.start();
}
}

 

在本例中,使用了一个生产者线程和一个消费者线程,当生产者线程往堆栈中添加字符时,如果堆栈已满,通过调用this.wait方法,(这里,this就是互斥锁)把自己加入到互斥锁对象(SyncStack)的锁等待队列中,如果该堆栈不满,则该生产者线程加入到互斥锁对象(SyncStack)的锁申请队列中,并且很快就被JVM取出来执行。当生产者线程在执行添加字符操作的时候,消费者是不能从中取出字符的,只能在等待队列中等待,当生产者添加完字符的时候,使用this.notify()(这里,this就是互斥锁)把等待队列中的第一个消费者唤醒,把它加入到锁申请队列中,很快该消费者线程就会获得CPU时间。此时的生产者线程已经无法再次添加字符,因为消费者线程正在synchronized代码块中运行,JVM把生产者线程加入锁等待队列中。当消费者线程从堆栈中取完字符后,再使用this.notify()方法把生产者从等待进程中唤醒,添加字符,如此循环往复,直到生产者线程和消费者线程都运行结束。

消费者与生产者

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
问题描述:有一群生产者进程在不断生产产品,而另一群消费者进程在不断消费生产出的产品;为了了解
生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将
wait()和notify()¬ifyAll()必须工作在加锁(synchronized)的代码块中。 抢占的锁和释放的锁要是
生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将
架构设计:生产者/消费者模式 http://www.sina.com.cn 2009年07月30日 00:49 IT168.com 文本Tag:
java线程的生命周期 /** * 公共资源类 */ public class PublicResource { private int number = 0;
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程
2009-03 作者:编程随想 来源:编程随想的博客 [0]:概述 今天打算来介绍一下“生产者/消费者模式
本章目标 加深线程同步操作的理解 了解Object类中对线程的支持方法 实例要求 在线程操作中有一个经
原来写过一个....我都忘记了.. http://fair-jm.iteye.com/blog/1894288 以上这个不对啊..看了下和所
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号