自從Java 1.5之后,在java.util.concurrent包下提供了若干個阻塞隊列,主要有以下幾個: ArrayBlockingQueue:基於數組實現的一個阻塞隊列,在創建ArrayBlockingQueue對象時必須制定容量大小。並且可以指定公平性與非公平性,默認情況下為非公平的,即不保證等待時間最長的隊列最優先能夠訪問隊列。 LinkedBlockingQueue:基於鏈表實現的一個阻塞隊列,在創建LinkedBlockingQueue對象時如果不指定容量大小,則默認大小為Integer.MAX_VALUE。 PriorityBlockingQueue:以上2種隊列都是先進先出隊列,而PriorityBlockingQueue卻不是,它會按照元素的優先級對元素進行排序,按照優先級順序出隊,每次出隊的元素都是優先級最高的元素。注意,此阻塞隊列為無界阻塞隊列,即容量沒有上限(通過源碼就可以知道,它沒有容器滿的信號標志),前面2種都是有界隊列。 DelayQueue:基於PriorityQueue,一種延時阻塞隊列,DelayQueue中的元素只有當其指定的延遲時間到了,才能夠從隊列中獲取到該元素。DelayQueue也是一個無界隊列,因此往隊列中插入數據的操作(生產者)永遠不會被阻塞,而只有獲取數據的操作(消費者)才會被阻塞。
功能說明:由於部署阿里雲的SLS日志服務,寫了個日志接口,考慮到系統日志量提交有可能會阻塞,這里引入了線程池(生存者與消費者模式)來維護日志隊列的發送。一個發送消息模塊將消息發送到消息隊列中,無需等待返回結果,發送模塊繼續執行其他任務。消息隊列中的指令由線程池中的線程來處理。使用一個Queue來存放線程池溢出時的任務
public class ThreadPoolManager { private static ThreadPoolManager tpm = new ThreadPoolManager(); // 線程池維護線程的最少數量 private final static int CORE_POOL_SIZE = 4; // 線程池維護線程的最大數量 private final static int MAX_POOL_SIZE = 10; // 線程池維護線程所允許的空閑時間 private final static int KEEP_ALIVE_TIME = 0; // 線程池所使用的緩沖隊列大小 private final static int WORK_QUEUE_SIZE = 10; // 消息緩沖隊列 Queue<String> msgQueue = new LinkedList<String>(); // 訪問消息緩存的調度線程 // 查看是否有待定請求,如果有,則創建一個新的AccessDBThread,並添加到線程池中 final Runnable accessBufferThread = new Runnable() { @Override public void run() { if(hasMoreAcquire()){ String msg = ( String ) msgQueue.poll(); Runnable task = new AccessDBThread( msg ); threadPool.execute( task ); } } }; final RejectedExecutionHandler handler = new RejectedExecutionHandler(){ @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { System.out.println(((AccessDBThread )r).getMsg()+"消息放入隊列中重新等待執行"); msgQueue.offer((( AccessDBThread ) r ).getMsg() ); } }; // 管理數據庫訪問的線程池 @SuppressWarnings({ "rawtypes", "unchecked" }) final ThreadPoolExecutor threadPool = new ThreadPoolExecutor( CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,new ArrayBlockingQueue( WORK_QUEUE_SIZE ), this.handler); // 調度線程池 final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool( 100 ); @SuppressWarnings("rawtypes") final ScheduledFuture taskHandler = scheduler.scheduleAtFixedRate(accessBufferThread, 0, 1, TimeUnit.SECONDS); public static ThreadPoolManager newInstance() { return tpm; } private ThreadPoolManager(){} private boolean hasMoreAcquire(){ return !msgQueue.isEmpty(); } public void addLogMsg( String msg ) { Runnable task = new AccessDBThread( msg ); threadPool.execute( task ); } }
//線程池中工作的線程 public class AccessDBThread implements Runnable { private String msg; public AccessDBThread() { super(); } public AccessDBThread(String msg) { this.msg = msg; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } @Override public void run() { // 向數據庫中添加Msg變量值 System.out.println("Added the message: "+msg+" into the Database"); } }
//TestDriver.java是一個驅動測試,sendMsg方法不間斷的向ThreadPoolManager發送數據 public class TestDriver { ThreadPoolManager tpm = ThreadPoolManager.newInstance(); public void sendMsg( String msg ) { tpm.addLogMsg( msg + "記錄一條日志 " ); } public static void main(String[] args) { for(int i=0;i<1000;i++){ new TestDriver().sendMsg( Integer.toString( i ) ); } //new TestDriver().sendMsg("發起一條對象" ); } }
參考資料:
http://www.cnblogs.com/dolphin0520/p/3958019.html
http://www.cnblogs.com/dolphin0520/p/3932906.html
http://www.360doc.com/content/11/1126/19/1332348_167587893.shtml
http://www.360doc.com/content/06/0812/16/8473_179457.shtml
http://ifeve.com/java-blocking-queue/