2011-10-19 139 views
0

我有一個線程,add() s對象到LinkedList隊列中,另一個線程是poll()是要處理對象的隊列。這些是我在隊列中使用的唯一兩種方法。我永遠不會遍歷隊列,也不會在列表中添加也不會刪除對象。我不能想到兩個線程互相踩踏並以某種方式破壞數據的場景,但也許我的想象力簡直就是缺乏。LinkedList隊列和線程安全

推送頻率很低(每秒幾次),但投票非常頻繁(每秒幾千次)。我想知道在同步add()poll()時會得到多少懲罰。這是在Android上運行。我不是在尋找BlockingQueue;我在I/O上阻塞,而不是在隊列中的對象上:

輪詢線程上的run()方法阻止等待空間在輸出緩衝區中可用的塊。空間變得可用時,它會查看是否有任何對象在隊列中等待。如果有一個可用,則將其序列化到輸出緩衝區中。如果隊列爲空(即,poll()返回null),則其它較低優先級隊列,如果全部爲空,則序列化「無數據可用」消息。

+0

不要緊的開銷是什麼?您有兩個線程競爭訪問相同資源:您**需要**同步。對於它的價值通常並不那麼糟糕。 – corsiKa

+0

爲什麼你甚至投票呢?你能直接發送一個'消息'給另一個線程(用新的對象)嗎? Checkout Loopers和Handlers的實施細節 – smith324

+0

感謝您提供Looper建議。我對Android特定的庫很少有經驗 - 感謝您將這一個引起我的注意。我可以看到,工作,有點。接收線程不能立即處理對象,因爲它接收到它們 - 它會阻塞IO寫入。爲了使這項工作,我需要在接收線程中的隊列的本地副本。想想吧,我不確定這是否可能 - 據我所知,Loopers阻止了他們的消息隊列,並且我需要阻止我的IO。 – iter

回答

2

沒有同步,你可能會遇到閱讀線程輪詢一個對象已經被添加到隊列中,並且該列表還沒有完全退出add()方法。

如果你看看源代碼,可以用「expectedModCount = l.modCount;」來解決問題。因爲在modC​​ount被實際修改之前,輪詢的鎖存基於它下面的一行。

本質上,你的刪除發生在完美的時間,可能帶有1個元素,同時又添加另一個元素,並且出錯。

爲了防止出現這種情況,可以將訪問包裝在同步(第一)塊中,或者可以使用併發類。我更喜歡併發隊列,因爲poll不必旋轉 - 你可以有一個阻塞take()。

你可能在尋找:java.util.concurrent.ArrayBlockingQueue中

ArrayBlockingQueue<String> que = new ArrayBlockingQueue<String>(100); 
    que.add(""); 
    que.take(); 
+0

感謝您的失敗情況。我正在爲我的代碼添加同步。 BlokingQueue是解決不同問題的巧妙解決方案。我編輯我的原始問題來解釋我阻止IO而不是隊列。 – iter

5

umn不android有BlockingQueues?他們是專爲這種情況設計,不知道爲什麼你想要使用其他任何東西 - 不能得到更有效的..

+1

是的,Android有'java.util.concurrent'和類似'LinkedBlockingQueue'的東西。強烈建議在這種情況下。 – CommonsWare

+0

謝謝您的建議。我看到我原來的問題不清楚,我是在阻止IO而不是數據可用性。我編輯這個問題來詳細說明這一點。 – iter

+0

@iter您的場景不會阻止您使用BlockingQueues。你明顯可以自己實現同步(BlockingQueues作爲列表或數組實現起來相當簡單),但是你也可以使用LinkedList和Array實現中存在的'poll()'方法。或者你可以使用'Collections.synchronizedList'和co - 如果我必須猜測所有三種變體(包括自我實現)應該從性能角度來看基本相同。 – Voo