最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程編程中使用Condition類操作鎖的方法詳解

 更新時間:2016年07月11日 08:59:28   作者:三千分之一的愛  
Condition是java.util.concurrent.locks包下的類,提供了對線程鎖的更精細(xì)的控制方法,下面我們就來看一下Java多線程編程中使用Condition類操作鎖的方法詳解

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

Condition函數(shù)列表

// 造成當(dāng)前線程在接到信號或被中斷之前一直處于等待狀態(tài)。
void await()
// 造成當(dāng)前線程在接到信號、被中斷或到達指定等待時間之前一直處于等待狀態(tài)。
boolean await(long time, TimeUnit unit)
// 造成當(dāng)前線程在接到信號、被中斷或到達指定等待時間之前一直處于等待狀態(tài)。
long awaitNanos(long nanosTimeout)
// 造成當(dāng)前線程在接到信號之前一直處于等待狀態(tài)。
void awaitUninterruptibly()
// 造成當(dāng)前線程在接到信號、被中斷或到達指定最后期限之前一直處于等待狀態(tài)。
boolean awaitUntil(Date deadline)
// 喚醒一個等待線程。
void signal()
// 喚醒所有等待線程。
void signalAll()

Condition類用法示例
Condition 將 Object 監(jiān)視器方法(wait、notify 和 notifyAll)分解成截然不同的對象,以便通過將這些對象與任意 Lock 實現(xiàn)組合使用,為每個對象提供多個等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監(jiān)視器方法的使用。下面將之前寫過的一個線程通信的例子替換成用Condition實現(xiàn),代碼如下:

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都可以實現(xiàn),這里注意,Condition是被綁定到Lock上的,要創(chuàng)建一個Lock的Condition必須用newCondition()方法。
這樣看來,Condition和傳統(tǒng)的線程通信沒什么區(qū)別,Condition的強大之處在于它可以為多個線程間建立不同的Condition,下面引入API中的一段代碼,加以說明。

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

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

2. 判斷count是否為100,顯然沒有100;

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

4. 判斷當(dāng)前寫入的索引位置++后,是否和100相等,相等將寫入索引值變?yōu)?,并將count+1;
5. 僅喚醒讀線程阻塞隊列中的一個;

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

7. ……

8. 僅喚醒寫線程阻塞隊列中的一個。

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

相關(guān)文章

  • 高級數(shù)據(jù)結(jié)構(gòu)及應(yīng)用之使用bitmap進行字符串去重的方法實例

    高級數(shù)據(jù)結(jié)構(gòu)及應(yīng)用之使用bitmap進行字符串去重的方法實例

    今天小編就為大家分享一篇關(guān)于高級數(shù)據(jù)結(jié)構(gòu)及應(yīng)用之使用bitmap進行字符串去重的方法實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • 解析java.library.path和LD_LIBRARY_PATH的介紹與區(qū)別

    解析java.library.path和LD_LIBRARY_PATH的介紹與區(qū)別

    這篇文章主要介紹了java.library.path和LD_LIBRARY_PATH的介紹與區(qū)別,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-05-05
  • 手把手教你排查解決Java編譯報錯:找不到符號

    手把手教你排查解決Java編譯報錯:找不到符號

    這篇文章主要介紹了手把手教你排查解決Java編譯報錯:找不到符號的相關(guān)資料,提供了排查步驟和解決方法,通過這些步驟,開發(fā)者可以有效地找到并解決編譯器拋出的找不到符號錯誤,從而提高開發(fā)效率,需要的朋友可以參考下
    2025-04-04
  • 多方面解讀Java中的volatile關(guān)鍵字

    多方面解讀Java中的volatile關(guān)鍵字

    這篇文章主要介紹了多方面解讀Java中的volatile關(guān)鍵字,它的作用是強制對被修飾的變量的寫操作立即刷新到主存中,并強制對該變量的讀操作從主存中讀取最新的值,而不是使用緩存中的值,需要的朋友可以參考下
    2023-05-05
  • 解析MyBatisPlus解決邏輯刪除與唯一索引的兼容問題

    解析MyBatisPlus解決邏輯刪除與唯一索引的兼容問題

    這篇文章主要介紹了MyBatisPlus解決邏輯刪除與唯一索引的兼容問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • java設(shè)計模式--七大原則詳解

    java設(shè)計模式--七大原則詳解

    本篇文章主要對Java中的設(shè)計模式如,創(chuàng)建型模式、結(jié)構(gòu)型模式和行為型模式以及7大原則進行了歸納整理,需要的朋友可以參考下,希望能給你帶來幫助
    2021-07-07
  • 深入理解Java8新特性之Stream API的創(chuàng)建方式和中間操作步驟

    深入理解Java8新特性之Stream API的創(chuàng)建方式和中間操作步驟

    Stream是Java8的一大亮點,是對容器對象功能的增強,它專注于對容器對象進行各種非常便利、高效的 聚合操作(aggregate operation)或者大批量數(shù)據(jù)操作。Stream API借助于同樣新出現(xiàn)的Lambda表達式,極大的提高編程效率和程序可讀性,感興趣的朋友快來看看吧
    2021-11-11
  • Java面試題沖刺第三天--集合框架篇

    Java面試題沖刺第三天--集合框架篇

    這篇文章主要為大家分享了最有價值的三道java面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-07-07
  • MyBatis全局配置文件詳解

    MyBatis全局配置文件詳解

    這篇文章主要介紹了mybatis 加載配置文件的方法,通過實例代碼給大家介紹了mybatis 加載配置文件的兩種方式,需要的朋友可以參考下
    2021-07-07
  • Java連接MySQL數(shù)據(jù)庫命令行程序過程

    Java連接MySQL數(shù)據(jù)庫命令行程序過程

    SQL編程包括兩種形式,一種是過程化編程,主要通過數(shù)據(jù)庫交互式工具,通過存儲過程、觸發(fā)器、函數(shù)等形式的編程;另一種是嵌入式SQL編程,將SQL語句嵌入到高級開發(fā)語言,完成數(shù)據(jù)的各種操作
    2021-10-10

最新評論

郑州市| 大同县| 萨嘎县| 修文县| 平安县| 寻乌县| 通榆县| 繁峙县| 黔西| 准格尔旗| 黄冈市| 长丰县| 保亭| 新闻| 雅江县| 胶南市| 黔东| 康定县| 池州市| 乌拉特后旗| 尤溪县| 兴隆县| 南宁市| 庆安县| 布拖县| 新建县| 麻栗坡县| 南华县| 宜兴市| 来宾市| 平江县| 郓城县| 瓦房店市| 福建省| 浪卡子县| 慈溪市| 台山市| 邢台市| 丰县| 建始县| 汽车|