java Semaphore 信號量的使用:java
在java中,提供了信號量Semaphore的支持。面試
Semaphore類是一個計數信號量,必須由獲取它的線程釋放,
一般用於限制能夠訪問某些資源(物理或邏輯的)線程數目。數據庫
一個信號量有且僅有3種操做,且它們所有是原子的:初始化、增長和減小
增長能夠爲一個進程解除阻塞;
減小可讓一個進程進入阻塞。緩存
--若是朋友您想轉載本文章請註明轉載地址"http://www.cnblogs.com/XHJT/p/3910406.html "謝謝-- 服務器
信號量維護一個許可集,如有必要,會在得到許可以前阻塞每個線程:
//今後信號量獲取給定數目的許可,在提供這些許可前一直將線程阻塞。
acquireUninterruptibly(int permits){}
每個release()添加一個許可,從而可能釋放一個正在阻塞的獲取者。
Semaphore只對可用許可的號碼進行計數,並採起相應的行動。
如何得到Semaphore對象?
public Semaphore(int permits,boolean fair)
permits:初始化可用的許可數目。
fair: 若該信號量保證在徵用時按FIFO的順序授予許可,則爲true,不然爲false;
如何從信號量得到許可?
public void acquire() throws InterruptedExceptionide
如何釋放一個許可,並返回信號量?
public void release()
代碼實例:
20我的去銀行存款,可是該銀行只有兩個辦公櫃檯,有空位則上去存錢,沒有空位則只能去排隊等待post
package com.xhj.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * 線程信號量Semaphore的運用 * * @author XIEHEJUN * */ public class SemaphoreThread { private int a = 0; /** * 銀行存錢類 */ class Bank { private int account = 100; public int getAccount() { return account; } public void save(int money) { account += money; } } /** * 線程執行類,每次存10塊錢 */ class NewThread implements Runnable { private Bank bank; private Semaphore semaphore; public NewThread(Bank bank, Semaphore semaphore) { this.bank = bank; this.semaphore = semaphore; } @Override public void run() { int b = a++; if (semaphore.availablePermits() > 0) { System.out.println("線程" + b + "啓動,進入銀行,有位置當即去存錢"); } else { System.out.println("線程" + b + "啓動,進入銀行,無位置,去排隊等待等待"); } try { semaphore.acquire(); bank.save(10); System.out.println(b + "帳戶餘額爲:" + bank.getAccount()); Thread.sleep(1000); System.out.println("線程" + b + "存錢完畢,離開銀行"); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 創建線程,調用內部類,開始存錢 */ public void useThread() { Bank bank = new Bank(); // 定義10個新號量 Semaphore semaphore = new Semaphore(2); // 創建一個緩存線程池 ExecutorService es = Executors.newCachedThreadPool(); // 創建20個線程 for (int i = 0; i < 10; i++) { // 執行一個線程 es.submit(new Thread(new NewThread(bank, semaphore))); } // 關閉線程池 es.shutdown(); // 從信號量中獲取兩個許可,而且在得到許可以前,一直將線程阻塞 semaphore.acquireUninterruptibly(2); System.out.println("到點了,工做人員要吃飯了"); // 釋放兩個許可,並將其返回給信號量 semaphore.release(2); } public static void main(String[] args) { SemaphoreThread test = new SemaphoreThread(); test.useThread(); } }
面試題思考:
在不少狀況下,可能有多個線程須要訪問數目不多的資源。假想在服務器上運行着若干個回答客戶端請求的線程。這些線程須要鏈接到同一數據庫,但任一時刻
只能得到必定數目的數據庫鏈接。你要怎樣纔可以有效地將這些固定數目的數據庫鏈接分配給大量的線程?
答:1.給方法加同步鎖,保證同一時刻只能有一我的去調用此方法,其餘全部線程排隊等待,可是此種狀況下即便你的數據庫連接有10個,也始終只有一個處於使性能用狀態。這樣將會大大的浪費系統資源,並且系統的運行效率很是的低下。學習
2.另一種方法固然是使用信號量,經過信號量許可與數據庫可用鏈接數相同的數目,將大大的提升效率和性能。