java並發之同步輔助類semaphore

來源:互聯網
上載者:User

標籤:java   訊號量   

semaphore(sem??f?r)含義:

訊號量就是可以聲明多把鎖(包括一把鎖:此時為互斥訊號量)。
舉個例子:一個房間如果只能容納5個人,多出來的人必須在門外面等著。如何去做呢?一個解決辦法就是:房間外面掛著五把鑰匙,每進去一個人就取走一把鑰匙,沒有鑰匙的不能進入該房間而是在外面等待。每出來一個人就把鑰匙放回原處以方便別人再次進入。

常用方法
acquire():擷取訊號量,訊號量內部計數器減1
release():釋放訊號量,訊號量內部計數器加1
tryAcquire():這個方法試圖擷取訊號量,如果能夠擷取返回true,否則返回false
訊號量控制的線程數量在聲明時確定。例如:
Semphore s = new Semphore(2);
一個例子
實現一個功能:一個列印佇列,被三台印表機列印

package semaphore;import java.util.concurrent.Semaphore;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class PrintQueue {    //訊號量private Semaphore semaphore;//是否空閑印表機private boolean freePrinters[];private Lock lockPrinters;public PrintQueue(){    //初始化三個訊號    semaphore=new Semaphore(3);    //三台空閑印表機    freePrinters=new boolean[3];    for (int i=0; i<3; i++){        freePrinters[i]=true;    }    lockPrinters=new ReentrantLock();}public void printJob (Object document){    try {        //擷取訊號量        semaphore.acquire();        int assignedPrinter=getPrinter();        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);        freePrinters[assignedPrinter]=true;    } catch (InterruptedException e) {        e.printStackTrace();    } finally {        // Free the semaphore        semaphore.release();                }}private int getPrinter() {    int ret=-1;    try {        lockPrinters.lock();        for (int i=0; i<freePrinters.length; i++) {            if (freePrinters[i]){                ret=i;                freePrinters[i]=false;                break;            }        }    } catch (Exception e) {        e.printStackTrace();    } finally {        lockPrinters.unlock();    }    return ret;}}

聲明一個Job類,使用列印佇列:

package semaphore;public class Job implements Runnable {     private PrintQueue printQueue;      public Job(PrintQueue printQueue){          this.printQueue=printQueue;     }      @Override      public void run() {         System.out.printf("%s: Going to print a job\n",Thread.currentThread().getName());         printQueue.printJob(new Object());         System.out.printf("%s: The document has been printed\n",Thread.currentThread().getName());             }}

測試:

package semaphore;public class MainCmd {    public static void main (String args[]){    PrintQueue printQueue=new PrintQueue();    //啟動12個列印線程    Thread thread[]=new Thread[12];    for (int i=0; i<12; i++){        thread[i]=new Thread(new Job(printQueue),"Thread "+i);    }    for (int i=0; i<12; i++){        thread[i].start();    }}}

需要注意的地方
1、對於訊號量聲明的臨界區,雖然可以控制線程訪問的數量,但是不能保證代碼塊之間是安全執行緒的。所以上面的例子在方法printJob()方法裡面使用了鎖保證資料安全性。
2、訊號量也涉及到公平性問題。和鎖公平性一樣,這裡預設是非公平的。可以通過構造器顯示聲明鎖的公平性。
public Semaphore(int permits, boolean fair)

應用情境
流量控制,即控制能夠訪問的最大線程數。

視頻擷取

java並發之同步輔助類semaphore

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.