java 鏈表併發隊列 LinkedBlockingQueue 的坑

鏈個隊比數組隊的性能要高, 所以一般用 LinkedBlockingQueue 比較多, 之前並沒有注意各方法有什麼不同.

環境: JDK 1.8

今天發現在 LinkedBlockingQueue 有個坑:

入隊方法 add不能隨意使用 :

LinkedBlockingQueue< String > receiveQueue = new LinkedBlockingQueue< String >();
receiveQueue.add("123");

會導致在出隊線程處理中 poll() 無法及時取得值:

/**
	 * 獨立處理 隊列線程
	 */
	private class receiveThread implements Runnable{
		@Override
		public void run() {
			String msg = null;
			while (receNext) {
				try {
					msg = receiveQueue.poll();
					if(msg != null) {
						//處理消息....
						logger.info("接收數據:"+ msg );
					} else {
						Thread.sleep(2000);
					}
				}catch (Exception e) {
					logger.error("接收線程異常", e);
				} finally {
					
				}
			}
		}
	}

經過查看原代碼, add方法在此類中沒有重寫, 入隊之後, 並沒有觸發操作, 因此是個坑.

重現的代碼環境是: 

1, add方法與poll所在的線程是在同一個類中, add在類方法中調用, poll 內部類線程中調用.

2, poll的線程一直在運行, 當程序中其它代碼(程序另一個線程中) 調用 add在一個方法後, poll並沒有取得值.

    經測試, 這時如果要poll要取得值必須 在poll之前調用 size() 才能讓poll取得值. 否則 poll在測試的 10多秒後仍然得到空值.

3, 以上是在多線程環境時出現的, 如果在同一段代碼中先 add再 poll這樣測試, 是可以正常取得值的.

經過測試與查看源代碼, 在此類中 出隊方法 receiveQueue.take(), 入隊方法 receiveQueue.put(E o)  應配合使用.

由於時間限制其它方法沒有再詳細測試.

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