JAVA线程并发数量控制_线程同步工具(二)控制并发访问多个资源
聲明:本文是《 Java 7 Concurrency Cookbook》的第三章, 作者: Javier Fernández González 譯者:鄭玉婷
控制并發(fā)訪問(wèn)多個(gè)資源
在并發(fā)訪問(wèn)資源的控制中,你學(xué)習(xí)了信號(hào)量(semaphores)的基本知識(shí)。
在上個(gè)指南,你實(shí)現(xiàn)了使用binary semaphores的例子。那種semaphores是用來(lái)保護(hù)訪問(wèn)一個(gè)共享資源的,或者說(shuō)一個(gè)代碼片段每次只能被一個(gè)線程執(zhí)行。但是semaphores也可以用來(lái)保護(hù)多個(gè)資源的副本,也就是說(shuō)當(dāng)你有一個(gè)代碼片段每次可以被多個(gè)線程執(zhí)行。
在這個(gè)指南中,你將學(xué)習(xí)怎樣使用semaphore來(lái)保護(hù)多個(gè)資源副本。你將實(shí)現(xiàn)的例子會(huì)有一個(gè)print queue但可以在3個(gè)不同的打印機(jī)上打印文件。
準(zhǔn)備
指南中的例子是使用 Eclipse IDE 來(lái)實(shí)現(xiàn)的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打開(kāi)并創(chuàng)建一個(gè)新的java任務(wù)。實(shí)現(xiàn)在控制并發(fā)訪問(wèn)資源里描述的例子。
怎么做呢…
按照這些步驟來(lái)實(shí)現(xiàn)下面的例子:
//1. 如我們之前提到的,你將實(shí)現(xiàn)semaphores來(lái)修改print queue例子。打開(kāi)PrintQueue類并聲明一個(gè)boolean array名為 freePrinters。這個(gè)array儲(chǔ)存空閑的等待打印任務(wù)的和正在打印文檔的printers。
private boolean freePrinters[];
//2. 接著,聲明一個(gè)名為lockPrinters的Lock對(duì)象。將要使用這個(gè)對(duì)象來(lái)保護(hù)freePrinters array的訪問(wèn)。
private Lock lockPrinters;
//3. 修改類的構(gòu)造函數(shù)并初始化新聲明的對(duì)象們。freePrinters array 有3個(gè)元素,全部初始為真值。semaphore用3作為它的初始值。
public PrintQueue(){
semaphore=new Semaphore(3);
freePrinters=new boolean[3];
for (int i=0; i<3; i++){
freePrinters[i]=true;
}
lockPrinters=new ReentrantLock();
}
//4. 修改printJob()方法。它接收一個(gè)稱為document的對(duì)象最為唯一參數(shù)。
public void printJob (Object document){
//5. 首先,調(diào)用acquire()方法獲得semaphore的訪問(wèn)。由于此方法會(huì)拋出 InterruptedException異常,所以必須加入處理它的代碼。
try {
semaphore.acquire();
//6. 接著使用私有方法 getPrinter()來(lái)獲得被安排打印任務(wù)的打印機(jī)的號(hào)碼。
int assignedPrinter=getPrinter();
//7.然后, 隨機(jī)等待一段時(shí)間來(lái)實(shí)現(xiàn)模擬打印文檔的行。
long duration=(long)(Math.random()*10);
System.out.printf("%s: PrintQueue: Printing a Job in Printer%d during %d seconds\n",Thread.currentThread().getName(), assignedPrinter,duration);
TimeUnit.SECONDS.sleep(duration);
//8. 最后,調(diào)用release() 方法來(lái)解放semaphore并標(biāo)記打印機(jī)為空閑,通過(guò)在對(duì)應(yīng)的freePrinters array引索內(nèi)分配真值。
freePrinters[assignedPrinter]=true;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
//9. 實(shí)現(xiàn) getPrinter() 方法。它是一個(gè)私有方法,返回一個(gè)int值,并不接收任何參數(shù)。
private int getPrinter() {
//10. 首先,聲明一個(gè)int變量來(lái)保存printer的引索值。
int ret=-1;
//11. 然后, 獲得lockPrinters對(duì)象 object的訪問(wèn)。
try {
lockPrinters.lock();
//12. 然后,在freePrinters array內(nèi)找到第一個(gè)真值并在一個(gè)變量中保存這個(gè)引索值。修改值為false,因?yàn)榈葧?huì)這個(gè)打印機(jī)就會(huì)被使用。
for (int i=0; i
if (freePrinters[i]){
ret=i;
freePrinters[i]=false;
break;
}
}
//13. 最后,解放lockPrinters對(duì)象并返回引索對(duì)象為真值。
} catch (Exception e) {
e.printStackTrace();
} finally {
lockPrinters.unlock();
}
return ret;
//14. Job 和 Core 類不做任何改變。
它是怎么工作的…
在例子中的PrintQueue類的關(guān)鍵是:Semaphore對(duì)象創(chuàng)建的構(gòu)造方法是使用3作為參數(shù)的。這個(gè)例子中,前3個(gè)調(diào)用acquire() 方法的線程會(huì)獲得臨界區(qū)的訪問(wèn)權(quán),其余的都會(huì)被阻塞 。當(dāng)一個(gè)線程結(jié)束臨界區(qū)的訪問(wèn)并解放semaphore時(shí),另外的線程才可能獲得訪問(wèn)權(quán)。
在這個(gè)臨界區(qū),線程獲得被分配打印的打印機(jī)的引索值。例子的這部分讓例子更真實(shí),而且它沒(méi)有使用任何與semaphores相關(guān)的代碼。以下的裁圖展示了這個(gè)例子的執(zhí)行輸出:
每個(gè)文檔都被安排到第一個(gè)空閑的打印機(jī)打印。
更多…
The acquire(), acquireUninterruptibly(), tryAcquire(),和release()方法有一個(gè)外加的包含一個(gè)int參數(shù)的版本。這個(gè)參數(shù)表示 線程想要獲取或者釋放semaphore的許可數(shù)。也可以這樣說(shuō),這個(gè)線程想要?jiǎng)h除或者添加到semaphore的內(nèi)部計(jì)數(shù)器的單位數(shù)量。在這個(gè)例子中acquire(), acquireUninterruptibly(), 和tryAcquire() 方法, 如果計(jì)數(shù)器的值小于許可值,那么線程就會(huì)被阻塞直到計(jì)數(shù)器到達(dá)或者大于許可值。
參見(jiàn)
總結(jié)
以上是生活随笔為你收集整理的JAVA线程并发数量控制_线程同步工具(二)控制并发访问多个资源的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 工行信用卡已制卡 收到卡片后激活才能使用
- 下一篇: AVR单片机计算器C语言源程序,AVR单