`
Donald_Draper
  • 浏览: 979936 次
社区版块
存档分类
最新评论

Condition实现消费生产者模型

    博客分类:
  • JUC
阅读更多
Condition条件变量很大一个程度上是为了解决Object.wait/notify/notifyAll难以使用的问题。
条件(也称为条件队列或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式释放相关的锁,并挂起当前线程,就像Object.wait 做的那样。上述API说明表明条件变量需要与锁绑定,而且多个Condition需要绑定到同一锁上。
前面的Lock中提到,获取一个条件变量的方法是Lock.newCondition()。
void await() throws InterruptedException; 
void awaitUninterruptibly(); 
long awaitNanos(long nanosTimeout) throws InterruptedException; 
boolean await(long time, TimeUnit unit) throws InterruptedException; 
boolean awaitUntil(Date deadline) throws InterruptedException; 
void signal(); 
void signalAll();

以上是Condition接口定义的方法,await*对应于Object.wait,signal对应于Object.notify,
signalAll对应于Object.notifyAll。特别说明的是Condition的接口改变名称就是为了避免
与Object中的wait/notify/notifyAll的语义和使用上混淆,因为Condition同样有wait/notify/notifyAll方法。每一个Lock可以有任意数据的Condition对象,Condition是与Lock绑定的,
所以就有Lock的公平性特性:如果是公平锁,线程为按照FIFO的顺序从Condition.await中释放,
如果是非公平锁,那么后续的锁竞争就不保证FIFO顺序了。一个使用Condition实现生产者消费者的模型例子如下:

package juc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Condition实现的生产者,消费者模型
 * 
 * @author donald 2017年3月2日 下午7:02:17
 * @param <T>
 */
public class ProductQueue<T> {
	private final T[] items;
	private final Lock lock = new ReentrantLock();
	private Condition notFull = lock.newCondition();// 队列非满条件
	private Condition notEmpty = lock.newCondition();// 队列非空条件
	//队列头,尾,当前容量
	private int head, tail, count;
    /**
     * 
     * @param maxSize
     */
	@SuppressWarnings("unchecked")
	public ProductQueue(int maxSize) {
		items = (T[]) new Object[maxSize];
	}

	public ProductQueue() {
		this(10);
	}
    /**
     * 生产
     * @param t
     * @throws InterruptedException
     */
	public void put(T t) throws InterruptedException {
		lock.lock();
		try {
			while (count == getCapacity()) {
				// ReentrantLock is oweself, await for realse the lock and put up
				// the thread
				// when the condition is satsfy ,the get the lock and run
				//如果当前队列已满,则等待不满条件
				notFull.await();
			}
			//添加到队列尾部
			items[tail] = t;
			if (++tail == getCapacity()) {
				//如果队列满,则将队列尾,执行队列,第一个槽
				tail = 0;
			}
			//增加队列元素个数
			++count;
			//释放非空信号,通知所有持有当前锁lock,并等待消费的线程
			notEmpty.signalAll();
		} finally {
			lock.unlock();
		}
	}
   /**
    * 消费
    * @return
    * @throws InterruptedException
    */
	public T take() throws InterruptedException {
		lock.lock();
		try {
			while (count == 0) {
				//如果队列为空,则等待非空条件
				notEmpty.await();
			}
			T ret = items[head];
			//取走队列头元素,并清空
			items[head] = null;// help GC
			//队列元素被取万,则head指向队列头
			if (++head == getCapacity()) {
				head = 0;
			}
			//减少队列元素数量
			--count;
			//释放非满信号,通知所有持有当前锁lock,并等待生产的线程
			notFull.signalAll();
			return ret;
		} finally {
			lock.unlock();
		}
	}
	/**
	 * 
	 * @return
	 */
	public int getCapacity() {
		return items.length;
	}
   /**
    * 
    * @return
    */
	public int size() {
		lock.lock();
		try {
			return count;
		} finally {
			lock.unlock();
		}
	}

}


在这个例子中消费take()需要队列不为空,如果为空就挂起(await()),直到收到notEmpty的信号;生产put()需要队列不满,如果满了就挂起(await()),直到收到notFull的信号。
0
0
分享到:
评论

相关推荐

    python实现生产者消费者并发模型

    多线程实现生产者消费者模型:锁(Lock)、信号量(Semaphore、BoundedSemaphore)、条件(Condition)、队列(Queue)、事件(Event) 多进程程实现生产者消费者模型:信号量(Semaphore)、条件(Condition)、...

    C++实现生产与消费者模型

    3. **生产者-消费者模型的实现** - **队列**:生产者和消费者之间通常会用到一个共享的缓冲区,也就是队列,用来存储生产者产生的数据供消费者消费。C++中可以使用`std::queue`容器来实现。 - **生产者**:生产者...

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

    3. **生产者消费者模型的实现步骤**: - 创建一个阻塞队列作为共享数据结构。 - 生产者线程负责向队列中添加元素,当队列满时,调用`put()`方法会阻塞生产者。 - 消费者线程负责从队列中移除元素,当队列空时,...

    生产者消费者模型的演变

    在Java中,`java.util.concurrent`包提供了多种实现生产者消费者模型的工具,如`BlockingQueue`。 `BlockingQueue`是Java并发编程的一个核心接口,它实现了队列的数据结构,并且具备线程安全的特性。生产者可以将...

    生产者消费者多进程模型Qt

    3. **条件变量**(Condition Variable):当缓冲区为空或满时,生产者和消费者可能需要等待,条件变量可以实现这种等待和唤醒机制。 4. **队列**:缓冲区通常以队列的形式实现,先进先出(FIFO)的特性保证了数据的...

    labview 生产者消费者例子

    通过对这些例程的分析和运行,可以深入理解生产者-消费者模型在LabVIEW中的实现方法。 8. **实际应用**:生产者-消费者模型在许多实际应用中都有所体现,如数据采集系统中,传感器作为生产者持续收集数据,而处理器...

    编程实现生产者消费者或读写者的同步问题

    在多线程环境中,生产者消费者模型和读者写者问题是经典的并发控制问题,它们都涉及到资源共享与同步。本主题将深入探讨如何使用编程来解决这两个问题。 首先,生产者消费者问题是多线程并发控制中的一个经典例子。...

    jchc.rar_tearshmj_生产者_生产者-消费者问题 c++ _生产者和消费者_生产者消费者

    首先,我们要理解生产者-消费者模型的基本概念。在这个模型中,生产者负责生产资源,而消费者则负责消耗这些资源。关键在于,生产者和消费者必须以一种协调的方式工作,以免出现资源过度消费或生产过剩的情况。这就...

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

    `BlockingQueue`接口提供了线程安全的队列,自动处理了等待和唤醒操作,是实现生产者-消费者模型的一种高效方式。 4. **条件变量**:`wait()`, `notify()`和`notifyAll()`是基于条件变量的,它们可以使得线程在特定...

    生产者消费者演示程序

    在计算机编程中,生产者消费者模型通常通过使用队列(Queue)数据结构来实现。队列是一种先进先出(FIFO)的数据结构,它提供了一种在生产者和消费者之间安全传递数据的方式。当生产者生成数据时,它会将数据放入...

    多进程同步-生产者消费者模式-C实现

    在计算机科学中,多进程同步是一个关键的概念,用于管理和协调多个并发执行的进程,确保它们在访问共享资源时不会产生冲突。在这个场景下,我们...这个C语言实现的生产者消费者模型是学习和提升这一技能的绝佳实践。

    Java实现生产者消费者模型

    Java实现生产者消费者模型 生产者消费者模型,是一般面试题都会考的,下面介绍使用ReetrantLock实现 生产者消费者模型。 定义一个ReentrantLock锁,同时new出两个condition,一个控制队满,一个 控制队空 //生产者 ...

    实验一 生产者消费者问题

    在提供的压缩包文件"实验一 生产者消费者问题"中,可能包含了一个具体的C++代码实现,展示了如何运用上述概念来构建生产者消费者模型。通过分析和理解这个代码,你可以深入学习到如何在C++中使用多线程和同步机制来...

    线程实现生产者消费者问题

    生产者消费者问题是多线程编程中的一个经典模型,用于演示如何在并发环境中通过共享资源进行协作。在这个模型中,生产者线程负责生成数据,而消费者线程则负责消费这些数据。问题的关键在于如何保证生产者不会在无处...

    并行openmp程序实现生产者消费者

    在《机械工业出版社 并行程序设计导论》第五章的练习题5.6中,可能要求读者设计并实现一个这样的模型,以理解和掌握OpenMP的并行化机制以及生产者消费者模式的基本概念。通常,这类练习会涉及到以下知识点: 1. **...

    生产者-消费者多线程处理

    生产者-消费者模型涉及到两个主要角色:生产者(Producer)和消费者(Consumer)。生产者负责生成数据或产品,并将其放入一个共享的缓冲区;而消费者则从这个缓冲区中取出并消费这些数据或产品。在我们的例子中,有...

    java 编写的生产者与消费者问题

    这个库提供了多种工具类,如Semaphore(信号量)、BlockingQueue(阻塞队列)和Condition(条件变量),这些都可以用来实现生产者-消费者模型。 1. **BlockingQueue**: 阻塞队列是一种特殊的队列,它具有线程安全的...

    生产者消费者问题 MFC

    生产者消费者问题是多线程编程中的一个经典案例,它展示了如何通过共享资源在并发环境中实现线程间的协调。在这个问题中,"生产者"线程负责生成数据,而"消费者"线程则负责消费这些数据。MFC(Microsoft Foundation ...

Global site tag (gtag.js) - Google Analytics