【Java并发编程实战】– 在同步代码中使用条件

1、概述

在并发编程中的一个经典问题是生产者与消费者问题:咱们有一个数据缓冲区,一个或多个数据的生产者在缓冲区存储数据,而一个或多个数据的消费者,把数据从缓冲区取出。java

因为缓冲区是一个共享的数据结构,咱们必须采用同步机制,好比 synchronized 关键字来控制对它的访问。可是咱们有更多的限制因素,若是缓冲区是满的,生产者不能存储数据,若是缓冲区是空的,消费者不能取出数据。编程

对于这些类型的状况,Java在Object对象中提供wait(),notify(),和notifyAll() 方法的实现。缓存

 wait() 方法:数据结构

      一、只能在同步代码块中调用并发

      二、当一个线程调用 wait() 方法,jvm将这个线程置入休眠,而且释放控制这个同步代码快的对象,同时容许其余线程执行这个对象控制的其余同步代码块jvm

      三、为了唤醒这个线程,必须在这个对象控制的某个同步代码快调用 notify() 方法或者 notifyAll() 方法ide

2、实现

import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 中间缓存
 */
public class EventStorage {

	private int maxSize;
	private LinkedBlockingQueue<Date> storage;
	
	public EventStorage(int maxSize){
		this.maxSize = maxSize;
		storage = new LinkedBlockingQueue<Date>();
	}
	
	// 存放操做
	public synchronized void set(){
		// 在while循环中,你必须保持检查条件和调用wait()方法。你不能继续执行,直到这个条件为true。
		while(storage.size() == maxSize){ //循环判断 为 真,才进行 线程 挂起操做.
			try {
				wait(); // 挂起 该线程,等待 剩余空间出现
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		storage.offer(new Date());
		System.out.println("存操做- storage size:" + storage.size());
		notifyAll(); // 唤醒 全部 由于 wait() 操做而休眠的 线程.
	}
	
	// 取出操做
	public synchronized void get(){
		while(storage.size() == 0){ //循环判断 为 真,才进行 线程 挂起操做.
			try {
				wait(); // 挂起 该线程,等待 剩余空间出现
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		storage.poll();
		System.out.println("取出操做- storage size:" + storage.size());
		notifyAll(); // 唤醒 全部 由于 wait() 操做而休眠的 线程.
	}
}
import java.util.concurrent.TimeUnit;

/**
 *  生产者
 */
public class EventProducer implements Runnable{

	private EventStorage eventStorage;
	
	public EventProducer(EventStorage eventStorage){
		this.eventStorage = eventStorage;
	}
	
	@Override
	public void run() {
	   while(true){
		   eventStorage.set();
		   try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	   }
	}
}
/**
 * 消费者
 */
public class EventCustomer implements Runnable{
    
    private EventStorage eventStorage;
	
	public EventCustomer(EventStorage eventStorage){
		this.eventStorage = eventStorage;
	}

	public void run() {
		while(true){
			eventStorage.get();
			try {
				TimeUnit.SECONDS.sleep(2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
public class EventTest {

	public static void main(String[] args) {
		EventStorage eventStorage = new EventStorage(3);
		
		EventProducer producer = new EventProducer(eventStorage);
		EventCustomer customer = new EventCustomer(eventStorage);
		
		Thread threadProducer = new Thread(producer);
		Thread threadCostomer = new Thread(customer);
		
		threadProducer.start();
		threadCostomer.start();
	}
}
相关文章
相关标签/搜索