Semaphore信號量應用

一、Semaphore(詳見JDK-API)
  一個計數信號量。從概念上講,信號量維護了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然後再獲取該許可。每個 release() 添加一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實際的許可對象,Semaphore 只對可用許可的號碼進行計數,並採取相應的行動。
二、應用場景
  在semamphore信號量非常適合高併發訪問,在新系統上線之前,要對系統的訪問量進行評估。當然這個值肯定不是隨隨便便就想出來的,是經過以往的經驗,數據,歷年的訪問量,已經推廣力度進行一個合理的評估,當然評估標準不能太大也不能太小,太大的話,投入的資源達不到實際的效果,純粹浪費資源,太小的話,某個時間點一個高峯值的訪問量上來可以直接壓垮系統。
   PV(page view)網站的總訪問量。頁面的瀏覽量或者點擊量,用戶每刷新一一次,或者點擊一次,就會被記錄。
   UV(unique visitor)獨立訪客。訪問網站的一臺電腦客戶端爲一個訪客,一般來講,時間從00到24點之內相同的ip客戶端只記錄一次。
   UV(query per second)即每秒查詢數。 qps很大程度上代表了系統業務上的繁忙程度,每次請求的背後,可能應對着多次磁盤I/O , 多次網絡請求,多個CPU時間片等。我們通過qps非常客觀的瞭解當前業務情況。一旦當前的qps超過了所設定的預警閥值,可以考慮增加機器對集羣擴容,以免壓力過大導致宕機,可以根據前期的壓力測試得到估值,在結合後期的綜合運維的情況,估算出閥值。
   RT(response time)請求的響應時間。 這個指標非常的關鍵,直接說明前端用戶的體驗,因此任何系統設計師都想降低RT時間
  當然還涉及cpu,內存,網絡,磁盤等情況,如select,delete,update等數據庫層面的東西
   容量評估。一般來說通過開發,運維,測試,以及業務相關人等。綜合出系統的一系列閥值,然後我們根據相關閥值如qps,rt等,對系統進行有效的變更。
   一般來講,進行多次壓力測試後,可以對系統進行峯值進行評估,採用所謂80/20原則,即80%的訪問請求,將在20%的訪問時間內達到,這樣我們可以根據系統對應的pv計算出峯值qps
   峯值qps=(總pv * 80%)/ ( 60 * 60 * 24 * 20% )
   然後再將總的峯值qps除以單臺機器所能承受的最高的qps值,就是所需要機器的數量.機器數量=總的峯值qps / 壓測得出的單機極限qps
  當然不排除系統在上線前進行大規模的促銷活動,或者雙十一,雙十二熱點事件,遭受到DDos攻擊等情況。系統的開發和運維人員急需要了解當前系統的運行狀態和負載情況,一般都會有後臺系統去維護。
   semaphore可以控制系統的流:拿到信號量的線程可以進入,否則就等待。通過acquire()和release()獲得或者釋放許可

public class UseSemaphore {  
  
    public static void main(String[] args) {  
        // 線程池  
        ExecutorService exec = Executors.newCachedThreadPool();  
        // 只能5個線程同時訪問  
        final Semaphore semp = new Semaphore(5);  
        // 模擬20個客戶端訪問  
        for (int index = 0; index < 20; index++) {  
            final int NO = index;  
            Runnable run = new Runnable() {  
                public void run() {  
                    try {  
                        // 獲取許可  
                        semp.acquire();  
                        System.out.println("Accessing: " + NO);  
                        //模擬實際業務邏輯
                        Thread.sleep((long) (Math.random() * 10000));  
                        // 訪問完後,釋放  
                        semp.release();  
                    } catch (InterruptedException e) {  
                    }  
                }  
            };  
            exec.execute(run);  
        } 
        
        try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
        
        //System.out.println(semp.getQueueLength());
        
        
        
        // 退出線程池  
        exec.shutdown();  
    }  
  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章