java中condition使用

1.Condition 將 Object 監視器方法(wait()、notify()和notifyAll())分解成截然不同的對象,以便通過將這些對象與任意Lock實現組合使用,爲每個對象提供多個等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監視器方法的使用。

  條件(也稱爲條件隊列 或條件變量)爲線程提供了一個含義,以便在某個狀態條件現在可能爲 true 的另一個線程通知它之前,一直掛起該線程(即讓其“等待”)。因爲訪問此共享狀態信息發生在不同的線程中,所以它必須受保護,因此要將某種形式的鎖與該條件相關聯。等待提供一個條件的主要屬性是:以原子方式 釋放相關的鎖,並掛起當前線程,就像 Object.wait 做的那樣。

  Condition 實例實質上被綁定到一個鎖上。要爲特定Lock實例獲得 Condition 實例,請使用其 newCondition()方法。作爲一個示例,假定有一個綁定的緩衝區,它支持 put 和 take 方法。如果試圖在空的緩衝區上執行 take 操作,則在某一個項變得可用之前,線程將一直阻塞;如果試圖在滿的緩衝區上執行 put 操作,則在有空間變得可用之前,線程將一直阻塞。我們喜歡在單獨的等待 set 中保存 put 線程和 take 線程,這樣就可以在緩衝區中的項或空間變得可用時利用最佳規劃,一次只通知一個線程。可以使用兩個Condition實例來做到這一點。

1. 定義消息管道

package com.java.test;

import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 存儲 生產者消息的通道
 * @author jiajie
 *
 */
public class MiddlewareChannel2 {
	public int init_capacity=0;//初始存儲  
	public int max_capacity=20;//最大存儲 最大容量值
	
	private Lock lock = new ReentrantLock();
	private Condition conumer = lock.newCondition();
	private Condition producer = lock.newCondition();
	
	/**
	 * 		  消息端產生消息
	 * 		  
	 * @param message
	 */
	public void send() {
		//拿到鎖
		try {
			lock.lock();
			//判斷通道是否已滿
			if(init_capacity > max_capacity) {   //已滿
				try {
					System.out.println("庫存已滿,生產者等待發送信息...");
					//生產者  等待發送消息
					producer.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}else {
				
				//通知消費者 消費消息
				System.out.println(Thread.currentThread().getName()+":生產消息" +"庫存容量:"+(++init_capacity));
				//喚醒所有消費者
				conumer.signalAll();
			}
			
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}finally {
			lock.unlock();
		}
		
		
		
		
	}
	
	/**
	 * 消息端 消費消息
	 */
	public void accept() {
		
		try {
			lock.lock();
			
			//判斷通道是否有消息
			if (init_capacity>0) {  //通道有消息
				 //彈出消息
				 System.out.println(Thread.currentThread().getName()+":消費消息:"+" 庫存容量:"+(--init_capacity));
				//消費完喚醒生產者 生產消息
			     producer.signalAll();
			}else {           //通道無消息
				try {
					System.out.println("庫存不足,等待生產者生產消息...");
					//等待消費
					conumer.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}finally {
			lock.unlock();
		}
	}

}

2發送端

package com.java.test;

/**
 * 生產者
 * @author jiajie
 *
 */
public class Producer implements Runnable{
	private MiddlewareChannel middlewareChannel;
	private String threadName;
	private String message;
	

	/**
	 * 構造通道類
	 * @param middlewareChannel
	 */
	public Producer(MiddlewareChannel middlewareChannel) {
		this.middlewareChannel = middlewareChannel;
	}

	/**
	 * 生產消息
	 */
	@Override
	public void run() {
		// TODO Auto-generated method stub
//		while (true) {
//			System.out.println(Thread.currentThread().getName());
//			middlewareChannel.send(message);
//		}
		
		for (int i = 0; i < 20; i++) {
//			System.out.println(Thread.currentThread().getName());
			middlewareChannel.send();
		}
	}
	
	
}

2.消費端

package com.java.test;

import javax.sound.midi.MidiChannel;

/**
 * 消費者
 * @author jiajie
 *
 */
public class Conumer implements Runnable{
	private MiddlewareChannel middlewareChannel;

	public Conumer(MiddlewareChannel middlewareChannel) {
		
		this.middlewareChannel = middlewareChannel;
	
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
//			System.out.println(Thread.currentThread().getName());
			middlewareChannel.accept();
		}
	
	}
	
}

3.測試

package com.java.test;

public class ClientTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//創建消息通道
		MiddlewareChannel middlewareChannel = new MiddlewareChannel();
		
		
		//創建消息消費者
		Conumer conumer1 = new Conumer(middlewareChannel);
		new Thread(conumer1,"消費者1").start();
		
//		//創建消息消費者
//		Conumer conumer2 = new Conumer(middlewareChannel);
//		new Thread(conumer2, "消費者2").start();
		
		//創建消息生產者1
		Producer producer1 = new Producer(middlewareChannel);
		new Thread(producer1,"生產者1").start();
		
//		//創建消息生產者2
//		Producer producer2 = new Producer(middlewareChannel, "我愛加班");
//		new Thread(producer2,"生產者2").start();
		
		
	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章