Semaphore也是一個線程同步的輔助類,可以維護當前訪問自身的線程個數,並提供了同步機制。使用Semaphore可以控制同時訪問資源的線程個數,例如,實現一個文件允許的並發訪問數。
Semaphore的主要方法摘要:
void acquire():從此信號量獲取一個許可,在提供一個許可前一直將線程阻塞,否則線程被中斷。
void release():釋放一個許可,將其返回給信號量。
int availablePermits():返回此信號量中當前可用的許可數。
boolean hasQueuedThreads():查詢是否有線程正在等待獲取。
下面是一個例子:
1 package com.thread; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.Semaphore; 6 7 public class SemaphoreTest { 8 public static void main(String[] args) { 9 ExecutorService service = Executors.newCachedThreadPool(); 10 final Semaphore sp = new Semaphore(3);//創建Semaphore信號量,初始化許可大小為3 11 for(int i=0;i<10;i++){ 12 try { 13 Thread.sleep(100); 14 } catch (InterruptedException e2) { 15 e2.printStackTrace(); 16 } 17 Runnable runnable = new Runnable(){ 18 public void run(){ 19 try { 20 sp.acquire();//請求獲得許可,如果有可獲得的許可則繼續往下執行,許可數減1。否則進入阻塞狀態 21 } catch (InterruptedException e1) { 22 e1.printStackTrace(); 23 } 24 System.out.println("線程" + Thread.currentThread().getName() + 25 "進入,當前已有" + (3-sp.availablePermits()) + "個並發"); 26 try { 27 Thread.sleep((long)(Math.random()*10000)); 28 } catch (InterruptedException e) { 29 e.printStackTrace(); 30 } 31 System.out.println("線程" + Thread.currentThread().getName() + 32 "即將離開"); 33 sp.release();//釋放許可,許可數加1 34 //下面代碼有時候執行不准確,因為其沒有和上面的代碼合成原子單元 35 System.out.println("線程" + Thread.currentThread().getName() + 36 "已離開,當前已有" + (3-sp.availablePermits()) + "個並發"); 37 } 38 }; 39 service.execute(runnable); 40 } 41 } 42 43 }
單個信號量的Semaphore對象可以實現互斥鎖的功能,並且可以是由一個線程獲得了“鎖”,再由另一個線程釋放“鎖”,這可應用於死鎖恢復的一些場合。
1 package com.thread; 2 import java.util.concurrent.ExecutorService; 3 import java.util.concurrent.Executors; 4 import java.util.concurrent.Semaphore; 5 import java.util.concurrent.locks.Lock; 6 import java.util.concurrent.locks.ReentrantLock; 7 8 public class LockTest { 9 public static void main(String[] args) { 10 final Business business = new Business(); 11 ExecutorService executor = Executors.newFixedThreadPool(3); 12 for(int i=0;i<3;i++) 13 { 14 executor.execute( 15 new Runnable() 16 { 17 public void run() 18 { 19 business.service(); 20 } 21 } 22 23 ); 24 } 25 executor.shutdown(); 26 } 27 28 private static class Business 29 { 30 private int count; 31 Lock lock = new ReentrantLock(); 32 Semaphore sp = new Semaphore(1); 33 public void service() 34 { 35 //lock.lock(); 36 try { 37 sp.acquire(); //當前線程使用count變量的時候將其鎖住,不允許其他線程訪問 38 } catch (InterruptedException e1) { 39 e1.printStackTrace(); 40 } 41 try { 42 count++; 43 try { 44 Thread.sleep(1000); 45 } catch (InterruptedException e) { 46 e.printStackTrace(); 47 } 48 System.out.println(count); 49 } catch (RuntimeException e) { 50 e.printStackTrace(); 51 } 52 finally 53 { 54 //lock.unlock(); 55 sp.release(); //釋放鎖 56 } 57 } 58 } 59 60 }
