程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java多線程編程中應用Condition類操作鎖的辦法詳解

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

編輯:關於JAVA

Java多線程編程中應用Condition類操作鎖的辦法詳解。本站提示廣大學習愛好者:(Java多線程編程中應用Condition類操作鎖的辦法詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是Java多線程編程中應用Condition類操作鎖的辦法詳解正文


Condition的感化是對鎖停止更准確的掌握。Condition中的await()辦法相當於Object的wait()辦法,Condition中的signal()辦法相當於Object的notify()辦法,Condition中的signalAll()相當於Object的notifyAll()辦法。分歧的是,Object中的wait(),notify(),notifyAll()辦法是和"同步鎖"(synchronized症結字)綁縛應用的;而Condition是須要與"互斥鎖"/"同享鎖"綁縛應用的。

Condition函數列表

// 形成以後線程在接到旌旗燈號或被中止之前一向處於期待狀況。
void await()
// 形成以後線程在接到旌旗燈號、被中止或達到指定期待時光之前一向處於期待狀況。
boolean await(long time, TimeUnit unit)
// 形成以後線程在接到旌旗燈號、被中止或達到指定期待時光之前一向處於期待狀況。
long awaitNanos(long nanosTimeout)
// 形成以後線程在接到旌旗燈號之前一向處於期待狀況。
void awaitUninterruptibly()
// 形成以後線程在接到旌旗燈號、被中止或達到指定最初刻日之前一向處於期待狀況。
boolean awaitUntil(Date deadline)
// 叫醒一個期待線程。
void signal()
// 叫醒一切期待線程。
void signalAll()

Condition類用法示例
Condition 將 Object 監督器辦法(wait、notify 和 notifyAll)分化成判然不同的對象,以便經由過程將這些對象與隨意率性 Lock 完成組合應用,為每一個對象供給多個期待 set (wait-set)。個中,Lock 替換了 synchronized 辦法和語句的應用,Condition 替換了 Object 監督器辦法的應用。上面將之前寫過的一個線程通訊的例子調換成用Condition完成,代碼以下:

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(),傳統線程的通訊方法,Condition都可以完成,這裡留意,Condition是被綁定到Lock上的,要創立一個Lock的Condition必需用newCondition()辦法。
如許看來,Condition和傳統的線程通訊沒甚麼差別,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/*隊列中存在的數據個數*/; 
 
  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;//個數++ 
    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;//個數-- 
    notFull.signal();//叫醒寫線程 
    return x; 
   } finally { 
    lock.unlock(); 
   } 
  }  
 } 

這是一個處於多線程任務情況下的緩存區,緩存區供給了兩個辦法,put和take,put是存數據,take是取數據,外部有個緩存隊列,詳細變量和辦法解釋見代碼,這個緩存區類完成的功效:有多個線程往外面存數據和從外面取數據,其緩存隊列(先輩先出落後後出)能緩存的最年夜數值是100,多個線程間是互斥的,當緩存隊列中存儲的值到達100時,將寫線程壅塞,並叫醒讀線程,當緩存隊列中存儲的值為0時,將讀線程壅塞,並叫醒寫線程,上面剖析一下代碼的履行進程:
1. 一個寫線程履行,挪用put辦法;

2. 斷定count能否為100,明顯沒有100;

3. 持續履行,存入值;

4. 斷定以後寫入的索引地位++後,能否和100相等,相等將寫入索引值變成0,並將count+1;
5. 僅叫醒讀線程壅塞隊列中的一個;

6. 一個讀線程履行,挪用take辦法;

7. ……

8. 僅叫醒寫線程壅塞隊列中的一個。

這就是多個Condition的壯大的地方,假定緩存隊列中曾經存滿,那末壅塞的確定是寫線程,叫醒的確定是讀線程,相反,壅塞的確定是讀線程,叫醒的確定是寫線程,那末假定只要一個Condition會有甚麼後果呢,緩存隊列中曾經存滿,這個Lock不曉得叫醒的是讀線程照樣寫線程了,假如叫醒的是讀線程,大快人心,假如叫醒的是寫線程,那末線程剛被叫醒,又被壅塞了,這時候又去叫醒,如許就糟蹋了許多時光。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved