Java 信號量 Semaphore 介紹

轉載自 :http://www.cnblogs.com/whgw/archive/2011/09/29/2195555.html http://blog.csdn.net/shihuacai/article/details/8856526

Semaphore當前在多線程環境下被擴放使用,操作系統的信號量是個很重要的概念,在進程控制方面都有應用。Java 併發庫 的Semaphore 可以很輕鬆完成信號量控制,Semaphore可以控制某個資源可被同時訪問的個數,通過 acquire() 獲取一個許可,如果沒有就等待,而 release() 釋放一個許可。比如在Windows下可以設置共享文件的最大客戶端訪問個數。 

Semaphore實現的功能就類似廁所有5個坑,假如有10個人要上廁所,那麼同時只能有多少個人去上廁所呢?同時只能有5個人能夠佔用,當5個人中 的任何一個人讓開後,其中等待的另外5個人中又有一個人可以佔用了。另外等待的5個人中可以是隨機獲得優先機會,也可以是按照先來後到的順序獲得機會,這取決於構造Semaphore對象時傳入的參數選項。單個信號量的Semaphore對象可以實現互斥鎖的功能,並且可以是由一個線程獲得了“鎖”,再由另一個線程釋放“鎖”,這可應用於死鎖恢復的一些場合。

Semaphore維護了當前訪問的個數,提供同步機制,控制同時訪問的個數。在數據結構中鏈表可以保存“無限”的節點,用Semaphore可以實現有限大小的鏈表。另外重入鎖 ReentrantLock 也可以實現該功能,但實現上要複雜些。 

相關方法:

acquire

public void acquire()
             throws InterruptedException
從此信號量獲取一個許可,在提供一個許可前一直將線程阻塞,否則線程被中斷。獲取一個許可(如果提供了一個)並立即返回,將可用的許可數減 1。

如果沒有可用的許可,則在發生以下兩種情況之一前,禁止將當前線程用於線程安排目的並使其處於休眠狀態:

  • 某些其他線程調用此信號量的 release() 方法,並且當前線程是下一個要被分配許可的線程;或者
  • 其他某些線程中斷當前線程。

如果當前線程:

  • 被此方法將其已中斷狀態設置爲 on ;或者
  • 在等待許可時被中斷

則拋出 InterruptedException,並且清除當前線程的已中斷狀態。 

拋出:
InterruptedException - 如果當前線程被中斷

release

public void release()
釋放一個許可,將其返回給信號量。釋放一個許可,將可用的許可數增加 1。如果任意線程試圖獲取許可,則選中一個線程並將剛剛釋放的許可給予它。然後針對線程安排目的啓用(或再啓用)該線程。

不要求釋放許可的線程必須通過調用 acquire() 來獲取許可。通過應用程序中的編程約定來建立信號量的正確用法。



下面的Demo中申明瞭一個只有5個許可的Semaphore,而有20個線程要訪問這個資源,通過acquire()和release()獲取和釋放訪問許可。

package deadLockThread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {
	
	public static void main(String[] args) {
		//線程池
		ExecutorService exec = Executors.newCachedThreadPool();
		//信號量  只能5個線程範問
	     final Semaphore semp = new Semaphore(5);
		//創建20個線程
		for (int i = 0; i < 20; i++) {
			final int no=i;
			Runnable run=new Runnable() {
				
				@Override
				public void run() {
					try {
						//獲取許可
						semp.acquire();
						System.out.println("Accessing"+no);
					    Thread.sleep((long) (Math.random() * 10000));
					    //釋放許可
					    semp.release();
						System.out.println("----------"+semp.availablePermits());
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					
				}
			};
			exec.execute(run);
			
		}  
		  
		  exec.shutdown();
		  
		
	}
	

}




發佈了34 篇原創文章 · 獲贊 45 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章