1. 程式人生 > >Java併發程式設計: 使用Semaphore限制資源併發訪問的執行緒數

Java併發程式設計: 使用Semaphore限制資源併發訪問的執行緒數

本文將介紹用來控制資源同時訪問個數的Semaphore工具類, 然後採用Semaphore給出一個泊車的例項,最後給出Semaphore和CountDownLatch的幾點比較. 

1. Semaphore工具類介紹

Java程式碼  收藏程式碼
  1. /** 
  2.  * A counting semaphore.  Conceptually, a semaphore maintains a set of 
  3.  * permits.  Each {@link #acquire} blocks if necessary until a permit is 
  4.  * available, and then takes it.  Each {@link #release} adds a permit,
     
  5.  * potentially releasing a blocking acquirer. 
  6.  * However, no actual permit objects are used; the <tt>Semaphore</tt> just 
  7.  * keeps a count of the number available and acts accordingly. 
  8.  * 
  9.  * <p>Semaphores are often used to restrict the number of threads than can 
  10.  * access some (physical or logical) resource.
     
  11.  */  


從Semaphore的註釋中可以看出如下幾點: 
1.從概念上講,訊號量維護了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然後再獲取該許可。每個 release() 新增一個許可,從而可能釋放一個正在阻塞的獲取者。 
2. Semaphore並不使用實際的許可物件,Semaphore 只對可用許可進行計數,並採取相應的行動。 

3.Semaphore 通常用於限制可以訪問某些資源(物理或邏輯的)的執行緒數目。 

Semaphore中定義了一個內部類Sync,該類繼承AbstractQueuedSynchronizer。 
從程式碼中可以看出,Semaphore的方法基本上都呼叫了Sync的方法來實現。Smaphore還提供了
公平非公平的兩種方式. 

Semaphore工具類相關的類圖以及詳細程式碼如下: 





Java程式碼  收藏程式碼
  1. /* 
  2.  * @(#)Semaphore.java   1.8 04/07/12 
  3.  * 
  4.  * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 
  5.  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
  6.  */  
  7. package java.util.concurrent;  
  8. import java.util.*;  
  9. import java.util.concurrent.locks.*;  
  10. import java.util.concurrent.atomic.*;  
  11. /** 
  12.  * A counting semaphore.  Conceptually, a semaphore maintains a set of 
  13.  * permits.  Each {@link #acquire} blocks if necessary until a permit is 
  14.  * available, and then takes it.  Each {@link #release} adds a permit, 
  15.  * potentially releasing a blocking acquirer. 
  16.  * However, no actual permit objects are used; the <tt>Semaphore</tt> just 
  17.  * keeps a count of the number available and acts accordingly. 
  18.  * 
  19.  * <p>Semaphores are often used to restrict the number of threads than can 
  20.  * access some (physical or logical) resource. For example, here is 
  21.  * a class that uses a semaphore to control access to a pool of items: 
  22.  * <pre> 
  23.  * class Pool { 
  24.  *   private static final MAX_AVAILABLE = 100; 
  25.  *   private final Semaphore available = new Semaphore(MAX_AVAILABLE, true); 
  26.  * 
  27.  *   public Object getItem() throws InterruptedException { 
  28.  *     available.acquire(); 
  29.  *     return getNextAvailableItem(); 
  30.  *   } 
  31.  * 
  32.  *   public void putItem(Object x) { 
  33.  *     if (markAsUnused(x)) 
  34.  *       available.release(); 
  35.  *   } 
  36.  * 
  37.  *   // Not a particularly efficient data structure; just for demo 
  38.  * 
  39.  *   protected Object[] items = ... whatever kinds of items being managed 
  40.  *   protected boolean[] used = new boolean[MAX_AVAILABLE]; 
  41.  * 
  42.  *   protected synchronized Object getNextAvailableItem() { 
  43.  *     for (int i = 0; i < MAX_AVAILABLE; ++i) { 
  44.  *       if (!used[i]) { 
  45.  *          used[i] = true; 
  46.  *          return items[i]; 
  47.  *       } 
  48.  *     } 
  49.  *     return null; // not reached 
  50.  *   } 
  51.  * 
  52.  *   protected synchronized boolean markAsUnused(Object item) { 
  53.  *     for (int i = 0; i < MAX_AVAILABLE; ++i) { 
  54.  *       if (item == items[i]) { 
  55.  *          if (used[i]) { 
  56.  *            used[i] = false; 
  57.  *            return true; 
  58.  *          } else 
  59.  *            return false; 
  60.  *       } 
  61.  *     } 
  62.  *     return false; 
  63.  *   } 
  64.  * 
  65.  * } 
  66.  * </pre> 
  67.  * 
  68.  * <p>Before obtaining an item each thread must acquire a permit from 
  69.  * the semaphore, guaranteeing that an item is available for use. When 
  70.  * the thread has finished with the item it is returned back to the 
  71.  * pool and a permit is returned to the semaphore, allowing another 
  72.  * thread to acquire that item.  Note that no synchronization lock is 
  73.  * held when {@link #acquire} is called as that would prevent an item 
  74.  * from being returned to the pool.  The semaphore encapsulates the 
  75.  * synchronization needed to restrict access to the pool, separately 
  76.  * from any synchronization needed to maintain the consistency of the 
  77.  * pool itself. 
  78.  * 
  79.  * <p>A semaphore initialized to one, and which is used such that it 
  80.  * only has at most one permit available, can serve as a mutual 
  81.  * exclusion lock.  This is more commonly known as a [i]binary 
  82.  * semaphore[/i], because it only has two states: one permit 
  83.  * available, or zero permits available.  When used in this way, the 
  84.  * binary semaphore has the property (unlike many {@link Lock} 
  85.  * implementations), that the "lock" can be released by a 
  86.  * thread other than the owner (as semaphores have no notion of 
  87.  * ownership).  This can be useful in some specialized contexts, such 
  88.  * as deadlock recovery. 
  89.  * 
  90.  * <p> The constructor for this class optionally accepts a 
  91.  * [i]fairness[/i] parameter. When set false, this class makes no 
  92.  * guarantees about the order in which threads acquire permits. In 
  93.  * particular, [i]barging[/i] is permitted, that is, a thread 
  94.  * invoking {@link #acquire} can be allocated a permit ahead of a 
  95.  * thread that has been waiting - logically the new thread places itself at 
  96.  * the head of the queue of waiting threads. When fairness is set true, the 
  97.  * semaphore guarantees that threads invoking any of the {@link 
  98.  * #acquire() acquire} methods are selected to obtain permits in the order in 
  99.  * which their invocation of those methods was processed 
  100.  * (first-in-first-out; FIFO). Note that FIFO ordering necessarily 
  101.  * applies to specific internal points of execution within these 
  102.  * methods.  So, it is possible for one thread to invoke 
  103.  * <tt>acquire</tt> before another, but reach the ordering point after 
  104.  * the other, and similarly upon return from the method. 
  105.  * Also note that the untimed {@link #tryAcquire() tryAcquire} methods do not 
  106.  * honor the fairness setting, but will take any permits that are 
  107.  * available. 
  108.  * 
  109.  * <p>Generally, semaphores used to control resource access should be 
  110.  * initialized as fair, to ensure that no thread is starved out from 
  111.  * accessing a resource. When using semaphores for other kinds of 
  112.  * synchronization control, the throughput advantages of non-fair 
  113.  * ordering often outweigh fairness considerations. 
  114.  * 
  115.  * <p>This class also provides convenience methods to {@link 
  116.  * #acquire(int) acquire} and {@link #release(int) release} multiple 
  117.  * permits at a time.  Beware of the increased risk of indefinite 
  118.  * postponement when these methods are used without fairness set true. 
  119.  * 
  120.  * @since 1.5 
  121.  * @author Doug Lea 
  122.  * 
  123.  */  
  124. public class Semaphore implements java.io.Serializable {  
  125.     private static final long serialVersionUID = -3222578661600680210L;  
  126.     /** All mechanics via AbstractQueuedSynchronizer subclass */  
  127.     private final Sync sync;  
  128.     /** 
  129.      * Synchronization implementation for semaphore.  Uses AQS state 
  130. 相關推薦

    Java併發程式設計——為IO密集型應用設計執行與劃分任務

    文章轉自:http://www.tuicool.com/articles/fA7rMn 實際工作中的三類程式適用於以併發的形式來提速: 1. 服務程式:同時響應多個使用者請求 2. 計算密集型程式:併發計算,將問題拆分為子任務、併發執行各子任務並最終將子任務的結果彙

    Java併發程式設計: 使用Semaphore限制資源併發訪問執行

    本文將介紹用來控制資源同時訪問個數的Semaphore工具類, 然後採用Semaphore給出一個泊車的例項,最後給出Semaphore和CountDownLatch的幾點比較.  1. Semaphore工具類介紹 Java程式碼  

    Guava併發:RateLimiter限制資源併發訪問執行

    RateLimiter類似於JDK的訊號量Semphore,他用來限制對資源併發訪問的執行緒數。 RateLimiter limiter = RateLimiter.create(4.0); //每秒不超過4個任務被提交 limiter.acquire();  //請求Ra

    Java併發程式設計(4):守護執行執行阻塞的四種情況

    守護執行緒Java中有兩類執行緒:User Thread(使用者執行緒)、Daemon Thread(守護執行緒) 使用者執行緒即執行在前臺的執行緒,而守護執行緒是執行在後臺的執行緒。 守護執行緒作用是為其他前臺執行緒的執行提供便利服務,而且僅在普通、非守護執行緒仍然執行時才需要,比如垃圾回收執行緒就是一個

    Java併發程式設計(8):多執行環境中安全使用集合API(含程式碼)

    Java併發程式設計(8):多執行緒環境中安全使用集合API(含程式碼)JAVA大資料中高階架構 2018-11-09 14:44:47在集合API中,最初設計的Vector和Hashtable是多執行緒安全的。例如:對於Vector來說,用來新增和刪除元素的方法是同步的。如果只有一個執行緒與Vector的例

    【搞定Java併發程式設計】第1篇:執行的五種可用狀態

    本文轉載自牛客網上一網友的回答:概括的解釋下執行緒的幾種可用狀態 第一種狀態:新建(new):新建了一個執行緒物件。例如,Thread thread = new Thread(); 第二種狀態:可執行狀態(Runnable):又叫“就緒狀態”。執行緒新建後,其他執行緒(比如main執行

    java併發程式設計(二)多個執行多個鎖

    多個執行緒多個鎖 多個執行緒多個鎖:多個執行緒,每個執行緒都可以拿到自己制定的鎖,分別獲得鎖之後,執行synchronized方法體的內容。就是在上次那個部落格上說道的鎖競爭的問題,是因為所有的執行緒過來以後都爭搶同一個鎖。如果說每個執行緒都可以或得到自己的鎖,這樣的話我們的鎖競爭問題就沒有了

    Java併發程式設計原理與實戰一(執行狀態及建立執行的多種方式)

    一、為什麼要學習併發程式設計 1.發揮多處理的強大能力 2.建模的簡單性 3.非同步事件的簡化處理 4.響應更加靈敏的使用者介面 二、併發的缺點 1.安全性問題 多執行緒環境下 多個執行緒共享一個資源 對資源進行非原子性操作 2.活躍

    Java併發程式設計之第一階段,多執行基礎深入淺出

    汪文君高併發程式設計第一階段01講-課程大綱及主要內容介紹 汪文君高併發程式設計第一階段02講-簡單介紹什麼是執行緒 汪文君高併發程式設計第一階段03講-建立並啟動執行緒 汪文君高併發程式設計第一階段04講-執行緒生命週期以及start方法原始碼剖析 汪文君高併發程式設計第

    java 併發程式設計學習筆記(八)執行

                                              &nb

    Java併發程式設計規則:原子變數實現執行安全

    判定規則: 如果一個類中存在變數,並且此變數的操作不是原子操作,那麼這個類就是非執行緒安全的類。線上程產生競爭條件的情況下,多執行緒訪問導致原子性不可保證。 競爭條件產生的原因: 當計算的正確性依賴於執行時中相關的時序或多執行緒的交替時,會產生競爭條件。多執行緒情況下,執行

    java併發程式設計(十五)之執行

    待續...package com.dason.juc2; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.co

    Java併發程式設計的藝術》讀書筆記—— 執行

                                  執行緒池 1.為什麼要引入執行緒池         昨天和一老鐵聊天時就說到了執行緒,他說執行緒是輕量級的程序,其實也可以這麼說吧。在《Ja

    Java併發程式設計】之八:多執行環境中安全使用集合API(含程式碼)

    在集合API中,最初設計的Vector和Hashtable是多執行緒安全的。例如:對於Vector來說,用來新增和刪除元素的方法是同步的。如果只有一個執行緒與Vector的例項互動,那麼,要求獲取

    java併發程式設計的藝術(五)-----執行狀態

    執行緒與程序? 執行緒是作業系統排程的最小單元,而程序是系統進行資源分配和排程的一個基本單位。 簡單理解:程序是程式的一次執行,執行緒可以理解為程序中的執行的一段程式片段 360解釋:程序是一個具有獨立功能的程式關於某個資料集合的一次執行活動。它可以申請和

    併發程式設計從入門到放棄1--執行安全性

    什麼是執行緒安全性?        當多個執行緒訪問某個類時,不管執行時環境採用何種排程方式或者這些程序將如何交替執行,並且在主調程式碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那麼就稱這個類是執行緒安全的。 執行緒安全性包括原子性,可見性

    理解Python併發程式設計一篇就夠了|執行

    前言 程式設計的樂趣之一是想辦法讓程式執行的越來越快,程式碼越寫越優雅。在剛開始學習併發程式設計時,相信你它會有一些困惑,本來這是一篇解釋多個併發開發的問題並幫助你快速瞭解併發程式設計的不同場景和應該使用的解決方案的文章,但是受微信文章長度限制和筆者對閱讀體驗的擔心,

    python併發程式設計之多程序、多執行、非同步和協程

    一、多執行緒   多執行緒就是允許一個程序記憶體在多個控制權,以便讓多個函式同時處於啟用狀態,從而讓多個函式的操作同時執行。即使是單CPU的計算機,也可以通過不停地在不同執行緒的指令間切換,從而造成多執行緒同時執行的效果。   多執行緒相當於一個併發(concunrr

    併發程式設計】通過命令列獲取執行資訊

    命令adb shell ps-t 檢視程序中執行緒的資訊-x 檢視utime和stime-P 檢視屬性-p 檢視排程策略,通常是檢視一個app處於前臺還是後臺-c 檢視哪一個CPU在執行這個程序name|pid 用名字或pid過濾例子(1) 檢視包名為com.eat的執行緒,

    JAVA網路程式設計實戰應用——雙向聊天(執行

    控制檯雙向聊天 Code Code 以下如果有些流不懂的話,看我之前關於IO流的文章 要先啟動服務端(Server),再啟動客戶端(Client) 必須要保證埠一致 Socket socket = new Socket(“lo