java多線程(複習-6)ReentrantLock之Condition

一,Condition的作用與Object.wait(),Object.notify()的作用相似

1,Condition是一個藉口,提供了幾個常用的方法。

void await() throws InterruptedException;使當前線程進入等待狀態,同時釋放鎖。與Object的wait()方法相似
void awaitUninterruptibly();和上一個相似,但是不會在等待過程中相應中斷
void signal();與Object.notify()相似
void signalAll();這兩個都是喚醒處於等待的線程,與Object.notifyAll()相似

2,Condition對象是由ReentrandLcok的類似工廠方法返回 一個ConditionObejct,該對象的構造方法由AQS提供。

二,使用Condition的方法來實現單一消費者生產者模式

package Akka構建高併發程序;

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

/**
 * 通知等待機制 實現消費者者/生產者模式
 */
public class PCDemo {
    //消費品
    public static class Data{
        public static String value = " ";
    }
    //使用一把把公共重入鎖
    public static Lock lock = new ReentrantLock();
    //使用lock 返回Condition對象
    public static  Condition condition = lock.newCondition();
    //生產者
    public static class Producer{

        public void setValue() throws Exception{
            try {
                lock.lock();
                if (!Data.value.equals(" ")){  //說明value沒有被消費
                    condition.await();
                }else{
                    String s = System.currentTimeMillis()+" ";
                    System.out.println("設置的value = " + s+"  當前線程的Name = "+Thread.currentThread().getName());
                    Data.value = s;//生產數據
                    condition.signal();//通知等待的消費者去消費
                }
            } finally {
                lock.unlock();
            }

        }
    }
    //消費者
    public static class Consumer{

        public void getValue() throws Exception{
            try {
                lock.lock();
                if (Data.value.equals(" ")){ //說明生產者沒有生產數據
                    condition.await();//消費者等待
                }else {
                    System.out.println("消費者獲得的值 "+ Data.value+"  當前線程的Name = "+Thread.currentThread().getName());
                    Data.value = " ";//模擬把數據消費了
                    condition.signal();//通知生產者趕快生產數據 ,我已經消費完了
                }
            } finally {
                lock.unlock();
            }

        }
    }

    //生產者線程
    public static class ProThread implements Runnable{
        private Producer producer;
        public ProThread(Producer p){
            this.producer = p;
        }

        @Override
        public void run() {
            while (true){
                try {
                    producer.setValue();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //消費者線程

    public static class ConThread implements Runnable{
        private Consumer consumer;
        public ConThread(Consumer consumer){
            this.consumer = consumer;
        }
        @Override
        public void run() {
            try {
                while (true){
                    consumer.getValue();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws Exception{
        Thread p = new Thread(new ProThread(new Producer()));
        Thread c = new Thread(new ConThread(new Consumer()));
        p.setName("Producer");
        c.setName("Consumer");
        p.start();
        c.start();
    }
}

運行結果與使用Object的方法一樣,

如果要通知多個線程,把signal()改爲signalAll()就好了,

參考:《Java高併發程序設計》

源碼分析參考:詳解Condition的await和signal等待/通知機制

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