Java多線程系列十——BlockingQueue類

來源:互聯網
上載者:User

標籤:center   ring   tac   request   str   常用   color   主線程   offer   

參考資料:http://ifeve.com/java-synchronousqueue/
http://www.cnblogs.com/jackyuj/archive/2010/11/24/1886553.html
http://ifeve.com/java-blocking-queue/

BlockingQueue的幾個API認識

方法 說明
add(E e) 添加元素,超出隊列size上限後拋異常
offer(E e) 添加元素,超出隊列size上限後拋異常,相比add官方更建議使用offer方法
put(E e) 添加元素,若空間不足則進入waiting狀態直到有空間
offer(E e, long timeout, TimeUnit unit) 添加元素,若空間不足則等待一定時間直到成功或者放棄
take() 擷取隊列頭部元素,若沒有可取元素則進入waiting狀態
poll(long timeout, TimeUnit unit) 擷取隊列頭部元素,若沒有可取元素則等待一定時間直到成功或者放棄
remove(Object o) 刪除元素

BlockingQueue派生出幾個常用的類ArrayBlockingQueue/LinkedBlockingDeque/DelayQueue/PriorityBlockingQueue/SynchronousQueue,類圖如下所示:

它們的一些特性:

  • ArrayBlockingQueue:以數組儲存元素,初始化時必須指定隊列的容量capacity,添加元素時若達到上限進入阻塞
  • LinkedBlockingDeque:以雙向鏈表儲存元素,初始化時可指定隊列的容量,若不指定,capacity預設為Integer.MAX_VALUE,添加元素時若達到上限進入阻塞
  • DelayQueue:以PriorityQueue儲存元表,只能擷取已到到期時間的元素,否則得到null,無容量上限,理論上可無限添加元素
  • PriorityBlockingQueue:以數組儲存元素,整個隊列為一棵平衡二叉樹,添加元素成功後對隊列內元素重排序,無容量上限,理論上可無限添加元素
  • SynchronousQueue:無緩衝隊列,生產者線程對其的插入操作put必須等待消費者的移除操作take,反過來也一樣

ArrayBlockingQueue的使用案例可參考Java多線程系列三——實現線程同步的方法,本文測試DelayQueue的使用,代碼如下:

import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;import java.util.concurrent.Callable;import java.util.concurrent.DelayQueue;import java.util.concurrent.Delayed;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.TimeUnit;/** * @Description 利用DelayQueue清除逾時請求<br/> *              1. 主線程從工作隊列取出任務處理完成後,把任務從逾時隊列移除<br/> *              2. 逾時檢查線程找到逾時請求後,把任務從工作隊列中移除 */public class DelayQueueTest {    public static void main(String[] args) throws InterruptedException, ExecutionException {        int size = 36;        DelayQueue<MyRequest> queue = new DelayQueue<>();// 用於記錄是否逾時的隊列        BlockingQueue<MyRequest> workQueue = new ArrayBlockingQueue<>(size);// 請求的隊表        Map<Integer, MyRequest> cache = new HashMap<>();// 請求與id的對照表        for (int i = 0; i < size; i++) {// 初始化            MyRequest impl = new MyRequest(i, System.nanoTime(), 120);            queue.put(impl);            workQueue.put(impl);            cache.put(i, impl);        }        /**         * 建立逾時檢查任務         */        Executors.newSingleThreadExecutor().submit(new Runnable() {            @Override            public void run() {                while (queue.size() > 0) {                    try {                        MyRequest impl = queue.take();                        workQueue.remove(impl);// 若請求逾時則把請求從隊列中移除                        System.out.println(String.format("%s is timeout", impl));                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        });        /**         * 建2個線程消費請求         */        ExecutorService executorService = Executors.newFixedThreadPool(2);        while (workQueue.size() > 0) {            List<MyRequest> tasks = Arrays.asList(new MyRequest[] { workQueue.take(), workQueue.take() });            List<Future<Integer>> futures = executorService.invokeAll(tasks);            for (Future<Integer> future : futures) {                queue.remove(cache.get(future.get()));// 若請求成功,則不需要再檢查是否逾時            }        }        executorService.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);        executorService.shutdown();    }}class MyRequest implements Delayed, Callable<Integer> {    private int threadId;    private long startTime;    private long expiredTime;    public MyRequest(int threadId, long startTime, long timeout) {        this.threadId = threadId;        this.startTime = startTime;        this.expiredTime = TimeUnit.SECONDS.toNanos(timeout) + System.nanoTime();    }    @Override    public Integer call() {        try {            Thread.sleep(TimeUnit.SECONDS.toMillis(10));        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(String.format("%s is ok", this));        return threadId;    }    @Override    public int compareTo(Delayed arg0) {        int rtn;        if (arg0 == null || !(arg0 instanceof MyRequest)) {            rtn = 1;        } else {            MyRequest impl = (MyRequest) arg0;            rtn = startTime > impl.getStartTime() ? 1 : (startTime == impl.getStartTime() ? 0 : -1);        }        return rtn;    }    @Override    public long getDelay(TimeUnit unit) {        return expiredTime - System.nanoTime();    }    public long getStartTime() {        return startTime;    }    @Override    public String toString() {        return String.format("MyRequest [threadId=%s, startTime=%s, expiredTime=%s]", threadId, startTime, expiredTime);    }}

 

Java多線程系列十——BlockingQueue類

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.