【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();
	}
}
相關文章
相關標籤/搜索