亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Condition-線程通信更高效的方式

dadong / 3039人閱讀

摘要:這樣看來(lái),和傳統(tǒng)的線程通信沒(méi)什么區(qū)別,的強(qiáng)大之處在于它可以為多個(gè)線程間建立不同的,下面引入中的一段代碼,加以說(shuō)明。

接近一周沒(méi)更新《Java線程》專欄了,主要是這周工作上比較忙,生活上也比較忙,呵呵,進(jìn)入正題,上一篇講述了并發(fā)包下的Lock,Lock可以更好的解決線程同步問(wèn)題,使之更面向?qū)ο?,并且ReadWriteLock在處理同步時(shí)更強(qiáng)大,那么同樣,線程間僅僅互斥是不夠的,還需要通信,本篇的內(nèi)容是基于上篇之上,使用Lock如何處理線程通信。

那么引入本篇的主角,Condition,Condition 將 Object 監(jiān)視器方法(wait、notify 和 notifyAll)分解成截然不同的對(duì)象,以便通過(guò)將這些對(duì)象與任意 Lock 實(shí)現(xiàn)組合使用,為每個(gè)對(duì)象提供多個(gè)等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和語(yǔ)句的使用,Condition 替代了 Object 監(jiān)視器方法的使用。下面將之前寫過(guò)的一個(gè)線程通信的例子替換成用Condition實(shí)現(xiàn)(Java線程(三)),代碼如下

    public class ThreadTest2 {  
        public static void main(String[] args) {  
            final Business business = new Business();  
            new Thread(new Runnable() {  
                @Override  
                public void run() {  
                    threadExecute(business, "sub");  
                }  
            }).start();  
            threadExecute(business, "main");  
        }     
        public static void threadExecute(Business business, String threadType) {  
            for(int i = 0; i < 100; i++) {  
                try {  
                    if("main".equals(threadType)) {  
                        business.main(i);  
                    } else {  
                        business.sub(i);  
                    }  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
    class Business {  
        private boolean bool = true;  
        private Lock lock = new ReentrantLock();  
        private Condition condition = lock.newCondition();   
        public /*synchronized*/ void main(int loop) throws InterruptedException {  
            lock.lock();  
            try {  
                while(bool) {                 
                    condition.await();//this.wait();  
                }  
                for(int i = 0; i < 100; i++) {  
                    System.out.println("main thread seq of " + i + ", loop of " + loop);  
                }  
                bool = true;  
                condition.signal();//this.notify();  
            } finally {  
                lock.unlock();  
            }  
        }     
        public /*synchronized*/ void sub(int loop) throws InterruptedException {  
            lock.lock();  
            try {  
                while(!bool) {  
                    condition.await();//this.wait();  
                }  
                for(int i = 0; i < 10; i++) {  
                    System.out.println("sub thread seq of " + i + ", loop of " + loop);  
                }  
                bool = false;  
                condition.signal();//this.notify();  
            } finally {  
                lock.unlock();  
            }  
        }  
    }  

在Condition中,用await()替換wait(),用signal()替換notify(),用signalAll()替換notifyAll(),傳統(tǒng)線程的通信方式,Condition都可以實(shí)現(xiàn),這里注意,Condition是被綁定到Lock上的,要?jiǎng)?chuàng)建一個(gè)Lock的Condition必須用newCondition()方法。

這樣看來(lái),Condition和傳統(tǒng)的線程通信沒(méi)什么區(qū)別,Condition的強(qiáng)大之處在于它可以為多個(gè)線程間建立不同的Condition,下面引入API中的一段代碼,加以說(shuō)明。

    class BoundedBuffer {  
       final Lock lock = new ReentrantLock();//鎖對(duì)象  
       final Condition notFull  = lock.newCondition();//寫線程條件   
       final Condition notEmpty = lock.newCondition();//讀線程條件   
      
       final Object[] items = new Object[100];//緩存隊(duì)列  
       int putptr/*寫索引*/, takeptr/*讀索引*/, count/*隊(duì)列中存在的數(shù)據(jù)個(gè)數(shù)*/;  
      
       public void put(Object x) throws InterruptedException {  
         lock.lock();  
         try {  
           while (count == items.length)//如果隊(duì)列滿了   
             notFull.await();//阻塞寫線程  
           items[putptr] = x;//賦值   
           if (++putptr == items.length) putptr = 0;//如果寫索引寫到隊(duì)列的最后一個(gè)位置了,那么置為0  
           ++count;//個(gè)數(shù)++  
           notEmpty.signal();//喚醒讀線程  
         } finally {  
           lock.unlock();  
         }  
       }  
      
       public Object take() throws InterruptedException {  
         lock.lock();  
         try {  
           while (count == 0)//如果隊(duì)列為空  
             notEmpty.await();//阻塞讀線程  
           Object x = items[takeptr];//取值   
           if (++takeptr == items.length) takeptr = 0;//如果讀索引讀到隊(duì)列的最后一個(gè)位置了,那么置為0  
           --count;//個(gè)數(shù)--  
           notFull.signal();//喚醒寫線程  
           return x;  
         } finally {  
           lock.unlock();  
         }  
       }   
     }  

這是一個(gè)處于多線程工作環(huán)境下的緩存區(qū),緩存區(qū)提供了兩個(gè)方法,put和take,put是存數(shù)據(jù),take是取數(shù)據(jù),內(nèi)部有個(gè)緩存隊(duì)列,具體變量和方法說(shuō)明見(jiàn)代碼,這個(gè)緩存區(qū)類實(shí)現(xiàn)的功能:有多個(gè)線程往里面存數(shù)據(jù)和從里面取數(shù)據(jù),其緩存隊(duì)列(先進(jìn)先出后進(jìn)后出)能緩存的最大數(shù)值是100,多個(gè)線程間是互斥的,當(dāng)緩存隊(duì)列中存儲(chǔ)的值達(dá)到100時(shí),將寫線程阻塞,并喚醒讀線程,當(dāng)緩存隊(duì)列中存儲(chǔ)的值為0時(shí),將讀線程阻塞,并喚醒寫線程,這也是ArrayBlockingQueue的內(nèi)部實(shí)現(xiàn)。下面分析一下代碼的執(zhí)行過(guò)程:

    1. 一個(gè)寫線程執(zhí)行,調(diào)用put方法;

    2. 判斷count是否為100,顯然沒(méi)有100;

    3. 繼續(xù)執(zhí)行,存入值;

    4. 判斷當(dāng)前寫入的索引位置++后,是否和100相等,相等將寫入索引值變?yōu)?,并將count+1;

    5. 僅喚醒讀線程阻塞隊(duì)列中的一個(gè);

    6. 一個(gè)讀線程執(zhí)行,調(diào)用take方法;

    7. ……

    8. 僅喚醒寫線程阻塞隊(duì)列中的一個(gè)。

這就是多個(gè)Condition的強(qiáng)大之處,假設(shè)緩存隊(duì)列中已經(jīng)存滿,那么阻塞的肯定是寫線程,喚醒的肯定是讀線程,相反,阻塞的肯定是讀線程,喚醒的肯定是寫線程,那么假設(shè)只有一個(gè)Condition會(huì)有什么效果呢,緩存隊(duì)列中已經(jīng)存滿,這個(gè)Lock不知道喚醒的是讀線程還是寫線程了,如果喚醒的是讀線程,皆大歡喜,如果喚醒的是寫線程,那么線程剛被喚醒,又被阻塞了,這時(shí)又去喚醒,這樣就浪費(fèi)了很多時(shí)間。

[摘自高爽|Coder] 原創(chuàng)地址:http://blog.csdn.net/ghsau/ar...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/69839.html

相關(guān)文章

  • Java基礎(chǔ)學(xué)習(xí)——多線程線程通信-生產(chǎn)者消費(fèi)者代碼示例)

    摘要:提供了多線程升級(jí)方案將同步替換成了顯示的操作。線程間通信接口可以替代傳統(tǒng)的線程間通信,用替換,用替換,用替換。商品執(zhí)行上述代碼,觀察結(jié)果可以看到,多個(gè)線程同時(shí)生產(chǎn)消費(fèi),由于指定喚醒互異線程,因此并不會(huì)引起錯(cuò)誤。 JDK 1.5提供了多線程升級(jí)方案將同步synchronized替換成了顯示的Lock操作??梢詫?shí)現(xiàn)喚醒、凍結(jié)指定的線程。 Lock接口Lock 實(shí)現(xiàn)提供了比使用 synchr...

    FuisonDesign 評(píng)論0 收藏0
  • Java 多線程并發(fā)編程面試筆錄一覽

    摘要:創(chuàng)建線程的方式方式一將類聲明為的子類。將該線程標(biāo)記為守護(hù)線程或用戶線程。其中方法隱含的線程為父線程。恢復(fù)線程,已過(guò)時(shí)。等待該線程銷毀終止。更多的使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前一直等待,除非線 知識(shí)體系圖: showImg(https://segmentfault.com/img/bVbef6v?w=1280&h=960); 1、線程是什么? 線程是進(jìn)程中獨(dú)立運(yùn)行的子任務(wù)。 2、創(chuàng)建線...

    bitkylin 評(píng)論0 收藏0
  • 線程同步與通信(4)——Lock 和 Condtion

    摘要:為了拓展同步代碼塊中的監(jiān)視器鎖,開(kāi)始,出現(xiàn)了接口,它實(shí)現(xiàn)了可定時(shí)可輪詢與可中斷的鎖獲取操作,公平隊(duì)列,以及非塊結(jié)構(gòu)的鎖。 前言 系列文章目錄 前面幾篇我們學(xué)習(xí)了synchronized同步代碼塊,了解了java的內(nèi)置鎖,并學(xué)習(xí)了監(jiān)視器鎖的wait/notify機(jī)制。在大多數(shù)情況下,內(nèi)置鎖都能很好的工作,但它在功能上存在一些局限性,例如無(wú)法實(shí)現(xiàn)非阻塞結(jié)構(gòu)的加鎖規(guī)則等。為了拓展同步代...

    Aceyclee 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<