多線程學習-隊列

1、常規隊列

      實現接口java.util.Queue,常用方法有offer、peek、poll等,分類:

      1)LinkedList:常規隊列,實現了接口List和Queue

      2)PriorityQueue:有序列表,加入到隊列中的元素,根據元素的天然排序或java.util.Comparator進行排序

public class PriorityQueueDemo {

	public static void main(String[] args) {
		//指定排序規則構造有序隊列
		PriorityQueue<Object> q1 = new PriorityQueue<Object>(num, new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2) {
				return 0;
			}
		});
		
		//默認構造,使用天然排序
		PriorityQueue<Object> q2 = new PriorityQueue<Object>();
	}

}

      3)ConcurrentLinkedQueue:基於鏈接節點的、線程安全的隊列,併發訪問不需要同步

2、阻塞隊列

      實現接口java.util.concurrent.BlockingQueue,通過put添加數據,沒有空間時阻塞,通過take獲取數據,沒有數據時阻塞

    1)ArrayBlockingQueue:數組支持的有界隊列

public class BlockingQueueDemo {
	private BlockingQueue<String> queue = new ArrayBlockingQueue<String>(num);

	public static void main(String[] args) {
		BlockingQueueDemo demo = new BlockingQueueDemo();
		
		Productor p = demo.new Productor();
		Consumer c = demo.new Consumer();
		p.start();
		c.start();
	}

	class Productor extends Thread{
		public void run(){
			try {
				//隊列添加數據
				queue.put("...");
			} catch (InterruptedException e) {
				//異常處理
			}
		}
	}
	
	class Consumer extends Thread{
		public void run(){
			try {
				//從隊列獲取數據
				String str = queue.take();
			} catch (InterruptedException e) {
				//異常處理
			}
		}
	}
}


    2)LinkedBlockingQueue: 鏈表支持的可選有界隊列,用法同ArrayBlockingQueue,只是後臺存儲方式不同

    3)PriorityBlockingQueue:由優先級堆支持的無界優先級隊列

    4)DelayQueue:由優先級堆支持的、基於時間的調度隊列,加入到隊列中的元素必須實現新的Delayed接口,主要實現2個方法getDelay(TimeUnit unit)和compareTo(Delayed d),其中getDelay方法返回的值應該是動態的,如果值固定的話,是負值還好說,可以直接獲取,如果是正值,獲取數據時將一直阻塞,參照源碼:

public E take() throws InterruptedException {
	final ReentrantLock lock = this.lock;
	lock.lockInterruptibly();
	try {
		for (;;) {
			E first = q.peek();
			if (first == null) {
				available.await();
			} else {
				long delay = first.getDelay(TimeUnit.NANOSECONDS);
				if (delay > 0) {
					long tl = available.awaitNanos(delay);
				} else {
					E x = q.poll();
					assert x != null;
					if (q.size() != 0)
						available.signalAll(); // wake up other takers
					return x;

				}
			}
		}
	} finally {
		lock.unlock();
	}
}


         因爲隊列的大小沒有界限,使得添加可以立即返回,但是在延遲時間過去之前,不能從隊列中取出元素。如果多個元素完成了延遲,那麼最早失效/失效時間最長的元素將第一個取出

        5)SynchronousQueue:同步隊列,每個插入操作必須等待另一個線程的對應移除操作,反之亦然。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章