`

消费者与生产者

阅读更多

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

线程同步是个老生常谈的问题了,在这里我将通过一个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()方法把生产者从等待进程中唤醒,添加字符,如此循环往复,直到生产者线程和消费者线程都运行结束。

分享到:
评论

相关推荐

    消费者与生产者 消费者与生产者 操作系统实验代码

    根据给定的文件信息,我们可以总结出以下关于“消费者与生产者”模型在操作系统中的实现相关的知识点: ### 1. 概述 “消费者与生产者”问题是一种经典的多线程编程模型,常用于解决资源有限制条件下的共享数据...

    消费者与生产者问题

    消费者与生产者问题是多线程编程中的一个经典案例,它主要涉及到线程间的协作与同步。在Java中,我们可以利用内置的并发库来实现这个问题。这个案例的核心是确保生产者线程不会在缓冲区满时继续生产,同时消费者线程...

    Java实现消费者与生产者两个线程问题

    用Java实现消费者与生产者两个线程进行调度

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

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

    消费者与生产者pv源语

    消费者与生产者 pv源语 java形式表达 信号量

    操作系统苹果橘子问题、读者写者问题、消费者与生产者问题

    关键挑战在于协调生产者和消费者的动作,确保缓冲区既不会溢出(当生产者过快而消费者过慢时),也不会为空(当消费者过快而生产者过慢时)。为此,可以使用阻塞队列或者其他同步原语,如信号量或条件变量,来控制...

    消费者与生产者.cpp

    消费者与生产者.cpp

    生产者消费者程序的实现

    生产者消费者的实现。可以自主地改变生产者,消费者的数目,和缓冲区。

    选择传统贸易还是跨境电商——销售渠道视角下消费者与生产者的决策分析.zip

    这篇压缩包内的文件《选择传统贸易还是跨境电商——销售渠道视角下消费者与生产者的决策分析》深入探讨了这两种销售模式对消费者和生产者的影响及决策因素。 首先,传统贸易通常指的是通过实体店、分销商或批发商...

    选择传统贸易还是跨境电商——销售渠道视角下消费者与生产者的决策分析.pdf

    由于给定内容存在大量的乱码和不完整信息,无法确切地从中提取和理解出有关“选择传统贸易还是跨境电商——销售渠道视角下消费者与生产者的决策分析”的具体知识点。但我将尽最大可能对标题和描述中提及的概念进行...

    消费者与生产者模型的Python简单实现

    消费者与生产者模型的Python简单实现

    生产者消费者_labview生产者消费者_

    同样,消费者也需要使用同步机制来防止与其他消费者同时读取。 3. **队列对象**:在LabVIEW中,队列对象是数据共享的关键。它可以是全局变量,也可以是通过消息传递机制传递的局部变量。队列的大小应该足够大,以...

    生产者消费者JAVA课程设计

    //下面的消费者类对象和生产者类对象所操作的是同一个同步堆栈对象 Producer p1 = new Producer(stack,ce); new Thread(p1).start();//生产者线程启动 Consumer c1 = new Consumer(stack,ce); new Thread(c1)....

    JAVA生产者与消费者同步问题

    java线程同步程序:消费者与生产者………………………………………………………………………………………………………………………………………………………………………………………………………………………………...

    消费者与生产者(windows下)

    此次试验是操作系统第七版de附加试验,但由于书上已经给出了关于这个问题的具体思路,这段代码只是根据那个思路写出来的产品。仅供参考。

    多生产者与多消费者问题c++源码

    多生产者,多消费者问题源代码多生产者,多消费者问题源代码多生产者,多消费者问题源代码多生产者,多消费者问题源代码多生产者,多消费者问题源代码多生产者,多消费者问题源代码多生产者,多消费者问题源代码多...

    生产者与消费者实验报告

    ### 生产者与消费者实验报告知识点详述 #### 一、引言 在计算机科学领域,生产者与消费者模型是一种经典的同步机制,被广泛应用于多线程编程、操作系统设计以及分布式系统架构中。该模型主要解决的是多个进程或...

    信号量来解决操作系统的消费者与生产者问题.rar_信号量_生产者 消费者_进程

    总结来说,这个程序通过信号量机制实现了进程间的同步与通信,有效地解决了生产者和消费者之间的竞争条件,保证了系统的稳定运行。通过深入理解信号量的工作原理以及其在生产者-消费者问题中的应用,我们可以更好地...

Global site tag (gtag.js) - Google Analytics