import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * 有時候線程取得lock後需要在一定條件下才能做某些工作,比如說經典的Producer和Consumer問題。 * 在Java 5.0以前,這種功能是由Object類的wait(), notify()和notifyAll()等方法實現的, * 在5.0裡面,這些功能集中到了Condition這個介面來實現。 */public class ConditionTest {/** * 籃子程式,這裡為了簡化問題,籃子中最多隻能有一個蘋果。 * Consumer必須在籃子裡有蘋果的時候才能吃蘋果,否則它必須暫時放棄對籃子的鎖定, * 等到Producer往籃子裡放了蘋果後再去拿來吃。而Producer必須等到籃子空了才能往裡放蘋果, * 否則它也需要暫時解鎖等Consumer把蘋果吃了才能往籃子裡放蘋果。 */public static class Basket {// 鎖Lock lock = new ReentrantLock();//根據鎖產生Condition對象Condition produced = lock.newCondition();Condition consumed = lock.newCondition();// 籃子中的蘋果數,最多為1int num = 0;/** * 生產蘋果,往籃子裡放 * @throws InterruptedException */public void produce() throws InterruptedException {// 獲得鎖lock.lock();System.out.println("Producer get a lock...");try {// 判斷是否滿足生產條件while (num == 1) {// 如果有蘋果,則不生產,放棄鎖,進入睡眠// 等待消費者消費System.out.println("Producer sleep...");consumed.await(); System.out.println("Producer awaked...");}/*生產蘋果*/Thread.sleep(500);System.out.println("Producer produced an Apple.");num = 1;// 通知等待produced Condition的線程produced.signal();} finally {lock.unlock();}}/** * 消費蘋果,從籃子中取 * @throws InterruptedException */public void consume() throws InterruptedException {// 獲得鎖lock.lock();System.out.println("Consumer get a lock...");try {// 判斷是否滿足消費條件while (num == 0) {// 如果沒有蘋果,無法消費,則放棄鎖,進入睡眠// 等待生產者生產蘋果System.out.println("Consumer sleep...");produced.await(); System.out.println("Consumer awaked...");}/*吃蘋果*/Thread.sleep(500);System.out.println("Consumer consumed an Apple.");num = 0;// 發訊號喚醒某個等待consumed Condition的線程consumed.signal();} finally {lock.unlock();}}}/** * 測試Basket程式 */public static void testBasket() throws Exception {final Basket basket = new Basket();//定義一個producerRunnable producer = new Runnable() {public void run() {try {basket.produce();} catch (InterruptedException ex) {ex.printStackTrace();}}};// 定義一個consumerRunnable consumer = new Runnable() {public void run() {try {basket.consume();} catch (InterruptedException ex) {ex.printStackTrace();}}};//各產生3個consumer和producerExecutorService service = Executors.newCachedThreadPool();for (int i = 0; i < 3; i++){service.submit(producer);}for (int i = 0; i < 3; i++){service.submit(consumer);}service.shutdown();} public static void main(String[] args) throws Exception {ConditionTest.testBasket();}}