欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java并發(fā)編程中構(gòu)建自定義同步工具

 更新時(shí)間:2015年04月14日 09:02:13   投稿:junjie  
這篇文章主要介紹了Java并發(fā)編程中構(gòu)建自定義同步工具,本文講解了可阻塞狀態(tài)依賴操作的結(jié)構(gòu)、有界緩存實(shí)現(xiàn)基類示例、阻塞實(shí)現(xiàn)方式一:拋異常給調(diào)用者、阻塞實(shí)現(xiàn)方式二:通過輪詢和休眠、阻塞實(shí)現(xiàn)方式三:條件隊(duì)列等內(nèi)容,需要的朋友可以參考下

當(dāng)Java類庫沒有提供適合的同步工具時(shí),就需要構(gòu)建自定義同步工具。

可阻塞狀態(tài)依賴操作的結(jié)構(gòu)

復(fù)制代碼 代碼如下:

acquir lock on object state;//請求獲取鎖
while(precondition does not hold){//沒有滿足前提條件
   release lock;//先釋放鎖
   wait until precondition might hold;//等待滿足前提條件
   optionlly fail if interrupted or timeout expires;//因?yàn)橹袛嗷蛘叱瑫r(shí)執(zhí)行失敗
   reacquire lock;//重新嘗試獲取鎖
}
perform action//執(zhí)行
   release lock;//釋放鎖

有界緩存實(shí)現(xiàn)基類示例

復(fù)制代碼 代碼如下:

public class BaseBoundBuffer<V> {
private final V[] buf;
private int tail;
private int head;
private int count;
@SuppressWarnings("unchecked")
public BaseBoundBuffer(int capacity) {
buf = (V[]) new Object[capacity];
}
public synchronized void doPut(V v) {
buf[tail] = v;
if (++tail == buf.length)
tail = 0;
count++;
}
public synchronized V doTake() {
V v = buf[head];

if (++head == buf.length)
head = 0;
count--;
return v;
}
public final synchronized boolean isFull() {
return count == buf.length;
}
public final synchronized boolean isEmpty() {
return count == 0;
}
}

阻塞實(shí)現(xiàn)方式一:拋異常給調(diào)用者

復(fù)制代碼 代碼如下:

public synchronized void put1(V v)  throws Exception{
if(isFull())
throw new Exception("full error");
doPut(v);
}

分析:異常應(yīng)該應(yīng)用于發(fā)生異常情況中,在這里拋異常不合適;需要調(diào)用者是處理前提條件失敗的情況,并沒有解決根本問題。
阻塞實(shí)現(xiàn)方式二:通過輪詢和休眠
復(fù)制代碼 代碼如下:

public void put2(V v) throws InterruptedException {
while (true) {//輪詢
synchronized (this) {
if (!isFull()) {
doPut(v);
return;    
}
}
Thread.sleep(SLEEP_TIME);//休眠
}
}

分析:很難權(quán)衡休眠時(shí)間SLEEP_TIME設(shè)置。如果設(shè)置過小,CPU可能會(huì)輪詢多次,消耗CPU資源也越高;如果設(shè)置過大,響應(yīng)性就越低。

阻塞實(shí)現(xiàn)方式三:條件隊(duì)列

條件隊(duì)列中的元素是一個(gè)個(gè)等待相關(guān)條件的線程。每個(gè)Java對象都可以作為一個(gè)鎖,每個(gè)對象同樣可以作為一個(gè)條件隊(duì)列,并且Object中的wait、notify、notifyAll方法就構(gòu)成了內(nèi)部條件隊(duì)列的API。Object.wait會(huì)自動(dòng)釋放鎖,并請求操作系統(tǒng)掛起當(dāng)前線程,從而使其它線程能獲得這個(gè)鎖并修改對象的狀態(tài)。Object.notify和Object.notifyAll能喚醒正在等待線程,從條件隊(duì)列中選取一個(gè)線程喚醒并嘗試重新獲取鎖。

復(fù)制代碼 代碼如下:

public synchronized void put3(V v) throws InterruptedException {
while(isFull())
wait();
doput(v);
notifyAll();
}

分析:獲得較好響應(yīng),簡單易用。

使用條件隊(duì)列​
1.條件謂詞

1).定義:條件謂詞是使某個(gè)操作成為狀態(tài)依賴操作的前提條件。條件謂詞是由類中各個(gè)狀態(tài)變量構(gòu)成的表達(dá)式。例如,對于put方法的條件謂詞就是“緩存不為空”。
2).關(guān)系:在條件等待中存在一種重要的三元關(guān)系,包括加鎖、wait方法和一個(gè)條件謂詞。在條件謂詞中包含多個(gè)狀態(tài)變量,而每個(gè)狀態(tài)變量必須由一個(gè)鎖來保護(hù),因此在測試條件謂詞之前必須先持有這個(gè)鎖。鎖對象和條件隊(duì)列對象(及調(diào)用wait和notify等方法所在的對象)必須是同一個(gè)對象。
3).約束:每次調(diào)用wait都會(huì)隱式地和特定的條件謂詞相關(guān)聯(lián),當(dāng)調(diào)用特定條件謂詞時(shí),調(diào)用者必須已經(jīng)持有與條件隊(duì)列相關(guān)的鎖,這個(gè)鎖必須還保護(hù)這組成條件謂詞的狀態(tài)變量

2.條件隊(duì)列使用規(guī)則

1).通常都有一個(gè)條件謂詞
2).永遠(yuǎn)在調(diào)用wait之前測試條件謂詞,并且在wait中返回后再次測試;
3).永遠(yuǎn)在循環(huán)中調(diào)用wait;
4).確保構(gòu)成條件謂詞的狀態(tài)變量被鎖保護(hù),而這個(gè)鎖必須與這個(gè)條件隊(duì)列相關(guān)聯(lián);
5).當(dāng)調(diào)用wait、notify和notifyAll時(shí),要持有與條件隊(duì)列相關(guān)聯(lián)的鎖;
6).在檢查條件謂詞之后,開始執(zhí)行被保護(hù)的邏輯之前,不要釋放鎖;

3.通知

盡量使用notifyAll,而不是nofify.因?yàn)閚ofify會(huì)隨機(jī)喚醒一個(gè)線程從休眠狀態(tài)變?yōu)锽locked狀態(tài)(Blocked狀態(tài)是種線程一直處于嘗試獲取鎖的狀態(tài),即一旦發(fā)現(xiàn)鎖可用,馬上持有鎖),而notifyAll會(huì)喚醒條件隊(duì)列中所有的線程從休眠狀態(tài)變?yōu)锽locked狀態(tài).考慮這么種情況,假如線程A因?yàn)闂l件謂詞Pa進(jìn)入休眠狀態(tài),線程B因?yàn)闂l件謂詞Pb進(jìn)入休眠狀態(tài).這時(shí)Pb為真,線程C執(zhí)行單一的notify.如果JVM隨機(jī)選擇了線程A進(jìn)行喚醒,那么線程A檢查條件謂詞Pa不為真后又進(jìn)入了休眠狀態(tài).從這以后再也沒有其它線程能被喚醒,程序會(huì)一直處于休眠狀態(tài).如果使用notifyAll就不一樣了,JVM會(huì)喚醒條件隊(duì)列中所有等待線程從休眠狀態(tài)變?yōu)锽locked狀態(tài),即使隨機(jī)選出一個(gè)線程一因?yàn)闂l件謂詞不為真進(jìn)入休眠狀態(tài),其它線程也會(huì)去競爭鎖從而繼續(xù)執(zhí)行下去.

4.狀態(tài)依賴方法的標(biāo)準(zhǔn)形式

復(fù)制代碼 代碼如下:

void stateDependentMethod throwsInterruptedException{
synchronized(lock){
while(!conditionPredicate))
lock.wait();
}
//dosomething();
....

notifyAll();
}

顯示Condition對象

顯示的Condition對象是一種更靈活的選擇,提供了更豐富的功能:在每個(gè)鎖上可以存在多個(gè)等待,條件等待可以是中斷的獲不可中斷的,基于時(shí)限的等待,以及公平的或非公平的隊(duì)列操作。一個(gè)Condition可以和一個(gè)Lock關(guān)聯(lián)起來,就像一個(gè)條件隊(duì)列和一個(gè)內(nèi)置鎖關(guān)聯(lián)起來一樣。要?jiǎng)?chuàng)建一個(gè)Condition,可以在相關(guān)聯(lián)的Lock上調(diào)用Lock.newCondition方法。以下用顯示條件變量重新實(shí)現(xiàn)有界緩存

復(fù)制代碼 代碼如下:

public class ConditionBoundedBuffer<V> {
 private final V[] buf;
 private int tail;
 private int head;
 private int count;
 private Lock lock = new ReentrantLock();
 private Condition notFullCondition = lock.newCondition();
 private Condition notEmptyCondition = lock.newCondition();
 @SuppressWarnings("unchecked")
 public ConditionBoundedBuffer(int capacity) {
  buf = (V[]) new Object[capacity];
 }

 public void doPut(V v) throws InterruptedException {
  try {
   lock.lock();
   while (count == buf.length)
    notFullCondition.await();
   buf[tail] = v;
   if (++tail == buf.length)
    tail = 0;
   count++;
   notEmptyCondition.signal();
  } finally {
   lock.unlock();
  }

 }

 public V doTake() throws InterruptedException {
  try {
   lock.lock();
   while (count == 0)
    notEmptyCondition.await();
   V v = buf[head];
   buf[head] = null;
   if (++head == buf.length)
    head = 0;
   count--;
   notFullCondition.signal();
   return v;
  } finally {
   lock.unlock();
  }
 }
}

相關(guān)文章

  • Java中的SpringAOP、代理模式、常用AspectJ注解詳解

    Java中的SpringAOP、代理模式、常用AspectJ注解詳解

    這篇文章主要介紹了Java中的SpringAOP、代理模式、常用AspectJ注解詳解,Spring提供了面向切面編程的豐富支持,允許通過分離應(yīng)用的業(yè)務(wù)邏輯與系統(tǒng)級服務(wù),例如審計(jì)和事務(wù)管理進(jìn)行內(nèi)聚性的開發(fā),需要的朋友可以參考下
    2023-09-09
  • spring?IOC容器管理必須知道的一些操作(基于XML方式)

    spring?IOC容器管理必須知道的一些操作(基于XML方式)

    Spring框架的核心是Spring容器,容器創(chuàng)建對象,將它們裝配在一起,配置它們并管理它們的完整生命周期,下面這篇文章主要給大家介紹了關(guān)于spring?IOC容器管理必須知道的一些操作,需要的朋友可以參考下
    2022-03-03
  • Maven 的配置文件路徑讀取方法

    Maven 的配置文件路徑讀取方法

    這篇文章主要介紹了Maven 的配置文件路徑讀取方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • SpringBoot簡單使用SpringData的jdbc和durid

    SpringBoot簡單使用SpringData的jdbc和durid

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著SpringBoot簡單使用SpringData的jdbc和durid,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • springMVC向Controller傳值出現(xiàn)中文亂碼的解決方案

    springMVC向Controller傳值出現(xiàn)中文亂碼的解決方案

    這篇文章主要介紹了springMVC向Controller傳值出現(xiàn)中文亂碼的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 一文詳解Java二分查找算法

    一文詳解Java二分查找算法

    二分查找(binary search),也稱折半搜索,是一種在有序數(shù)組中查找某一特定元素的搜索算法,接下來就來給大家講講都有哪些查找算法,以及經(jīng)典的二分查找法該如何實(shí)現(xiàn),需要的朋友可以參考下
    2023-07-07
  • 詳解Java 自動(dòng)裝箱與自動(dòng)拆箱

    詳解Java 自動(dòng)裝箱與自動(dòng)拆箱

    這篇文章主要介紹了Java 自動(dòng)裝箱與自動(dòng)拆箱的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-09-09
  • Java實(shí)現(xiàn)走迷宮回溯算法

    Java實(shí)現(xiàn)走迷宮回溯算法

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)走迷宮回溯算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 淺談springboot之JoinPoint的getSignature方法

    淺談springboot之JoinPoint的getSignature方法

    這篇文章主要介紹了springboot之JoinPoint的getSignature方法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • java使用httpclient模擬post請求和get請求示例

    java使用httpclient模擬post請求和get請求示例

    這篇文章主要介紹了java使用httpclient模擬post請求和get請求示例,需要的朋友可以參考下
    2014-02-02

最新評論