1. 程式人生 > >(java多執行緒併發)控制併發執行緒數的Semaphore

(java多執行緒併發)控制併發執行緒數的Semaphore

1.簡介
   訊號量(Semaphore),有時被稱為訊號燈,是在多執行緒環境下使用的一種設施, 它負責協調各個執行緒, 以保證它們能夠正確、合理的使用公共資源。

2.概念
    Semaphore分為單值和多值兩種,前者只能被一個執行緒獲得,後者可以被若干個執行緒獲得。

以一個停車場運作為例。為了簡單起見,假設停車場只有三個車位,一開始三個車位都是空的。這時如果同時來了五輛車,看門人允許其中三輛不受阻礙的進入,然後放下車攔,剩下的車則必須在入口等待,此後來的車也都不得不在入口處等待。這時,有一輛車離開停車場,看門人得知後,開啟車攔,放入一輛,如果又離開兩輛,則又可以放入兩輛,如此往復。

在這個停車場系統中,車位是公共資源,每輛車好比一個執行緒,看門人起的就是訊號量的作用。

     更進一步,訊號量的特性如下:訊號量是一個非負整數(車位數),所有通過它的執行緒(車輛)都會將該整數減一(通過它當然是為了使用資源),當該整數值為零時,所有試圖通過它的執行緒都將處於等待狀態。在訊號量上我們定義兩種操作: Wait(等待) 和 Release(釋放)。 當一個執行緒呼叫Wait(等待)操作時,它要麼通過然後將訊號量減一,要麼一直等下去,直到訊號量大於一或超時。Release(釋放)實際上是在訊號量上執行加操作,對應於車輛離開停車場,該操作之所以叫做“釋放”是因為加操作實際上是釋放了由訊號量守護的資源。

      在java中,還可以設定該訊號量是否採用公平模式,如果以公平方式執行,則執行緒將會按到達的順序(FIFO)執行,如果是非公平,則可以後請求的有可能排在佇列的頭部。
JDK中定義如下:
Semaphore(int permits, boolean fair)
  建立具有給定的許可數和給定的公平設定的Semaphore。

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

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

3.案例一:

package SemaPhore;

import java.util.Random;
import java.util.concurrent.*;
public class Test {



	public static void main(String[] args) {
		//執行緒池
		ExecutorService executor = Executors.newCachedThreadPool();
		//定義訊號量,只能5個執行緒同時訪問
        final Semaphore semaphore = new Semaphore(5);
        //模擬20個執行緒同時訪問
        for (int i = 0; i < 20; i++) {
        	 final int NO = i;
			 Runnable runnable = new Runnable() {
				public void run() {
					try {
						//獲取許可
						semaphore.acquire();
						//availablePermits()指的是當前訊號燈庫中有多少個可以被使用
						System.out.println("執行緒" + Thread.currentThread().getName() +"進入,當前已有" + (5-semaphore.availablePermits()) + "個併發");
					    System.out.println("index:"+NO);
						Thread.sleep(new Random().nextInt(1000)*10);
					    
						System.out.println("執行緒" + Thread.currentThread().getName() + "即將離開");	
					    //訪問完後,釋放
					    semaphore.release();

					
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			};
			
			executor.execute(runnable);
        }
        // 退出執行緒池
        executor.shutdown();
	}

}
4.案例二:

下面是模擬一個連線池,控制同一時間最多隻能有50個執行緒訪問。

  1. import java.util.UUID;  
  2. import java.util.concurrent.Semaphore;  
  3. import java.util.concurrent.TimeUnit;  
  4. publicclass TestSemaphore extends Thread {  
  5.     publicstaticvoid main(String[] args) {  
  6.         int i = 0;  
  7.         while (i < 500) {  
  8.             i++;  
  9.             new TestSemaphore().start();  
  10.             try {  
  11.                 Thread.sleep(1);  
  12.             } catch (InterruptedException e) {  
  13.                 e.printStackTrace();  
  14.             }  
  15.         }  
  16.     }  
  17.     /** 
  18.      * 控制某資源同時被訪問的個數的類 控制同一時間最後只能有50個訪問 
  19.      */
  20.     static Semaphore semaphore = new Semaphore(50);  
  21.     staticint timeout = 500;  
  22.     publicvoid run() {  
  23.         try {  
  24.             Object connec = getConnection();  
  25.             System.out.println("獲得一個連線" + connec);  
  26.             Thread.sleep(300);  
  27.             releaseConnection(connec);  
  28.         } catch (InterruptedException e) {  
  29.             e.printStackTrace();  
  30.         }  
  31.     }  
  32.     publicvoid releaseConnection(Object connec) {  
  33.         /* 釋放許可 */
  34.         semaphore.release();  
  35.         System.out.println("釋放一個連線" + connec);  
  36.     }  
  37.     public Object getConnection() {  
  38.         try {/* 獲取許可 */
  39.             boolean getAccquire = semaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS);  
  40.             if (getAccquire) {  
  41.                 return UUID.randomUUID().toString();  
  42.             }  
  43.         } catch (InterruptedException e) {  
  44.             e.printStackTrace();  
  45.         }  
  46.         thrownew IllegalArgumentException("timeout");  
  47.     }  
  48. }  

相關推薦

(java執行併發)控制併發執行Semaphore

1.簡介    訊號量(Semaphore),有時被稱為訊號燈,是在多執行緒環境下使用的一種設施, 它負責協調各個執行緒, 以保證它們能夠正確、合理的使用公共資源。 2.概念     Semaph

Java(三)併發控制15.執行的優先順序

class PriorityThread extends Thread { public PriorityThread(String name) { super(name); } public void run() { for(int i=0;

執行如何控制併發數量? Semaphore 執行協同類,用來控制執行併發數量

1、 Semaphore:執行緒協同類,用來控制執行緒併發數量,並且可以更加細粒度的進行控制, 因為真正被控制最大併發的程式碼放到了acquire和release之間。 2、主要方法:

JAVA執行(四) Executor併發框架向RabbitMQ推送訊息

github程式碼地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo  假設一個需求使用者點選某個頁面,我們後臺需要向MQ推送信資訊 1,模擬的MQ服務,我這邊使用RabbitMQ (關於MQ 傳送和監聽訊息可以

java執行系列翻譯之java併發/執行教程

原文地址:http://tutorials.jenkov.com/java-concurrency/index.html 以前計算機都是單核,同時只能執行一個程式。之後出現了多重任務處理,這意味著計算機同時可以處理多個程式(又名任務或流程)。但這不是真正的“同時執行”,只是單個CPU被多個程式共

JAVA執行併發面試問題

1. 程序和執行緒之間有什麼不同? 一個程序是一個獨立(self contained)的執行環境,它可以被看作一個程式或者一個應用。而執行緒是在程序中執行的一個任務。Java執行環境是一個包含了不同的類和程式的單一程序。執行緒可以被稱為輕量級程序。執行緒需要較少的資源來建立和駐留在程

總結-Java執行與高併發簡記

1、什麼是多執行緒? 一個程序可以開啟多個執行緒,每個執行緒可以併發/並行執行不同任務。 2、Java多執行緒實現方式    2.1、繼承Thread類    2.2、實現Runnable介面方式實現多執行緒    2.3、使

Java執行-併發執行

執行緒池有了解嗎? 答: java.util.concurrent.ThreadPoolExecutor 類就是一個執行緒池。客戶端呼叫ThreadPoolExecutor.submit(Runnable task) 提交任務,執行緒池內部維護的工作者執行緒的數量就是該執行緒池的執行

Java執行-併發之synchronized 關鍵字

synchronized 關鍵字 答: 底層實現: 進入時,執行 monitorenter,將計數器 +1,釋放鎖 monitorexit 時,計數器 -1 當一個執行緒判斷到計數器為 0 時,則當前鎖空閒,可以佔用;反之,當前執行緒進入等待狀態 含義

Java執行-併發之sleep() 和 wait(n) 、 wait() 的區別

sleep() 和 wait(n) 、 wait() 的區別 答: sleep 方法:是 Thread 類的靜態方法,當前執行緒將睡眠 n 毫秒,執行緒進入阻塞狀態。當睡眠時間到了,會接觸阻塞,進入可執行狀態,等待 CPU 的到來。睡眠不釋放鎖(如果有的話) wai

Java執行-併發執行產生死鎖的4個必要條件?如何避免死鎖?

多執行緒產生死鎖的4個必要條件? 答: 互斥條件:一個資源每次只能被一個執行緒使用 請求與保持條件:一個執行緒因請求資源而阻塞時,對已獲得的資源保持不放 不剝奪條件:程序已經獲得的資源,在未使用完之前,不能強行剝奪 迴圈等待條件:若干執行緒之間形成一種頭

Java執行-併發執行和程序的區別

執行緒和程序的區別 答: 程序是一個“執行中的程式”,是系統進行資源分配和排程的一個獨立單位 執行緒是程序的一個實體,一個程序中擁有多個執行緒,執行緒之間共享地址空間和其他資源(所以通訊和同步等操作執行緒比程序更加容易) 執行緒上下文的切換比程序上下文切換要快

Java執行-併發之如何制定執行執行順序?

文章目錄 如何讓10個執行緒按照順序列印0123456789? 程式碼如下: 1.建立一個鎖物件類 2.建立一個執行緒類 3.測試類 如何讓10個執行緒按照順序列印012

(CSDN遷移) JAVA執行實現-可控最大併發執行池(newFixedThreadPool)

上篇文章中介紹了單執行緒化執行緒池newSingleThreadExecutor,可控最大併發數執行緒池(newFixedThreadPool)與其最大的區別是可以通知執行多個執行緒,可以簡單的將newSingleThreadExecutor理解為newFixedThreadPool(1)。例如執行一下兩個程

Java執行程式設計核心技術(二)物件及變數的併發訪問

最近一直在忙比賽,四五個吧,時間有點緊張,部落格也沒時間更新~ 只能忙裡抽閒 本文屬於Java多執行緒程式設計系列的第二篇,旨在分享我對多執行緒程式設計技術的心得與感悟,順便做下筆記。 如果你閱讀完比較感興趣,歡迎關注我,等待更新後續篇章。 本文主要介紹Java多執行緒中的同步,也就是如何在Java語言中

java執行面試問答 & java併發面試問答

多執行緒和併發問題是Java技術面試中面試官比較喜歡問的問題之一。在這裡,從面試的角度列出了大部分重要的問題,但是你仍然應該牢固的掌握Java多執行緒基礎知識來對應日後碰到的問題。 Java多執行緒面試問題 1、程序和執行緒之間有什麼不同? 一個程序是一個獨立(self

java執行(含例項)、並行、併發的含義

轉  https://www.cnblogs.com/wxd0108/p/5479442.html 這篇文章寫得非常棒, 我在這裡記錄一下,防止以後找不到了   用多執行緒只有一個目的,那就是更好的利用cpu的資源,因為所有的多執行緒程式碼都可以用單執行緒來

Java 執行併發 1 — 幾個重要的概念

原子性: 和物理上的原子貌似沒多大關係,對於一系列的操作只能單個執行緒做處理,不能有其他執行緒干擾,例如多個人想往同一個杯子倒茶,但只有一個茶壺,只有等這個茶壺讓出來才能繼續讓其他人倒茶 有序性:

Java 執行併發 2 — CAS 無鎖

在 Java 併發程式設計裡面,最可愛的就是無鎖了,非常巧妙,精彩絕倫 額。O__O "… 那麼什麼是無鎖? 顧名思義,在併發情況下采用無鎖的方式實現物件操作的原子性,保證資料一致性、安全性、正確性

Java 執行併發 3.3 — Semaphore 共享鎖使用

Semaphore 是共享鎖的一種,字面上意思就是訊號量鎖 顧名思義,一個可以共享的鎖,可以讓多個執行緒共享同一把鎖,例如同一條馬路可以讓 4 臺車同時並行跑,相當於可以讓 4 個執行緒共享一把鎖,臨