簡體   English   中英

線程之間的Java同步列表。 最佳實踐

[英]Java Synchronised List between Threads. Best practice

當發生某些更改時,我正在創建數據庫日志記錄引擎。 這些更改將被推送到一個線程中的隊列,該線程每隔50ms處理隊列中的25個LogObject。

我正在考慮使用Collections.synchronizedList()來保存我仍然需要在線程中處理的對象。

主應用程序線程通過ThreadObjInstance.LogList.add(new LogObject("Something to log");將LogObjects推送到列表中ThreadObjInstance.LogList.add(new LogObject("Something to log");並且在線程中我執行LogObject x = LogList.shift();來處理它。

但是我覺得可能有更好的方法可以做到這一點,或者這是一種完全可以接受的方法嗎? 或者我應該使用ArrayBlockingQueue來處理他的情況? 或者另一個同步的列表對象......有很多選擇。

這是我第一次使用線程,所以我試圖弄清楚作業隊列的最佳方法是什么,以及用於維護它的對象。 我可以直接將內容添加到線程列表中嗎? 或者我需要在線程中使用同步方法嗎?

問題基本上是:

  1. 在哪里存儲同步的對象列表以在兩個線程之間進行處理(在處理線程或主線程中?)
  2. 從列表中添加/刪除項目的最佳做法是什么? 通過synchronized函數或直接在List對象上?
  3. 構建作業隊列時,我對List對象的選擇是什么?
  1. 您想要的任何地方,所有使用它的線程都可以訪問它。
  2. BlockingQueue就是這樣做的,您不需要自己進行任何同步。
  3. 眾多,但BlockingQueue在這種情況下是最直接的(生產者 - 消費者)。

您的選擇主要圍繞當您因某種原因備份隊列以及您想要使用多少內存時想要發生的事情。

如果你習慣停止主進程,直到日志記錄線程清除了一些隊列,那么ArrayBlockingQueue就可以了,因為它有界限(並且大小固定)並且在高負載下不會占用你的內存。

如果你習慣於在備份日志時忽略內存問題(也許你確定日志記錄線程將始終保持運行),那么LinkedBlockingQueue可能更適合,因為它稍微更優化並且是無限制的。 它也可以給出一個大小限制,但這是可選的。

如果您使用其中任何一個,則無需添加任何同步邏輯,因為它們自己完成所有操作。

在哪里存儲同步的對象列表以在兩個線程之間進行處理(在處理線程或主線程中?)

要么 - 您通常會在主線程中創建它並將其傳遞給您的日志記錄線程和處理線程,因為它們都將共享它。

從列表中添加/刪除項目的最佳做法是什么? 通過synchronized函數或直接在List對象上?

BlockingQueue提供了豐富的線程安全添加和刪除項API。

構建作業隊列時,我對List對象的選擇是什么?

往上看。

  1. 在這種情況下,似乎隊列屬於處理實體,即日志記錄線程。 但這只是一個概念上的決定,在一天結束時,他們都必須持有對某種共享對象的引用。
  2. 最好是公開一個添加項目的方法(你真的不想刪除),而不是暴露整個列表,免費濫用。 同樣,這與同步沒有任何關系,它只是封裝的基本原則,或者如果你願意的話,還是Demeter法則:只允許客戶做盡可能少的事情。 除了“我可以把事件放在這里”之外,主線程沒有理由知道你如何實現隊列(甚至是隊列)。
  3. 隊列可能最好由LinkedList表示,但由於隊列可能很小而且操作不在關鍵路徑上,因此選擇可能不重要。 使用最容易閱讀和理解的內容。 (我會考慮@Kayaman對BlockingQueue的建議,因為它需要你做很多工作,而且讀取代碼的人很容易弄清楚那里發生了什么。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM