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