iT邦幫忙

0

day18 了解結果收集與同步 (Concurrent Collections)

  • 分享至 

  • xImage
  •  

ConcurrentLinkedQueue:
一種「併發安全」的 Queue(佇列),多個執行緒可以同時寫入而不會互相干擾。
這樣就不用再加 synchronized,寫法更簡單。

synchronized 概念:
用關鍵字 synchronized 來保護程式區塊或方法,確保同一時間只有一個執行緒能存取共享資源。
缺點:效能可能比較差,因為鎖是「粗的」(一次鎖住整段程式碼),導致執行緒容易「排隊等鎖」。

只是一個小區塊要保護 -> synchronized
想要整個資料結構 ->(List/Map/Queue)能自動處理同步 Concurrent Collections
高併發、效能要求高 -> Concurrent Collections(效能更好)
資料結構簡單,偶爾才需要同步 -> Collections.synchronizedList() 也能用

任務直接往 Queue 塞結果
每個執行緒完成後 results.add(...),不用等 Future。 主執行緒最後再統一輸出。

有序性:
Queue 裡的順序是「任務完成的順序」,不是 port 的自然排序。
如果要保證 輸出依照 port 順序,就要用 Day16 那種 Future + List 的方法。

AtomicInteger:
一樣用來統計開啟的 port 數量,避免 race condition。

之前是用 List<Future> results 來收集掃描結果,最後再用迴圈 f.get() 一個個取出。
問題是:
如果結果數量很多,f.get() 會讓你等到全部任務結束才能看到結果。
如果多個執行緒同時存取同一個集合 (像是 ArrayList),會出現 執行緒安全問題 (Thread-safety issue)。
解決方式 → 使用 Java 提供的並發集合 (Concurrent Collections)
例如:
ConcurrentLinkedQueue → 無限長度、FIFO,適合即時收集結果
CopyOnWriteArrayList → 適合讀多寫少
ConcurrentHashMap → 適合 key-value 共享資料
BlockingQueue → 任務排程、結果同步

用GPT幫我生成的對照表格

面向 Day17: Future + List Day18: Concurrent Collection
結果儲存 List<Future<String>> results → 先存 任務的 Future ConcurrentLinkedQueue<String> → 直接存 字串結果
取得方式 f.get() 等待 Future 完成後再拿結果 (會阻塞) 任務完成後馬上 results.add(...),可立即取得
時間點 全部任務跑完後才收集並輸出結果 邊跑邊加,程式可邊掃描邊輸出結果
同步性 ArrayList 不是 thread-safe,但因為只在 main thread 收集結果,所以還算安全 ConcurrentLinkedQueue 是 thread-safe,允許多執行緒同時寫入
程式結構 需要兩段流程: (1) 提交任務 (2) 等待 Future 並取結果 一段流程即可:提交任務時就能把結果丟進集合
適合情境 - 要保證所有結果都完整拿到再處理 - 結果數量不大 - 需要即時處理 (像掃描器、即時監控) - 結果數量大,效率更好

今天我真正理解了「併發安全」在 Java 裡的意義。以前看到 synchronized 就覺得有點抽象,還不太懂什麼時候該用它,什麼時候不用。今天透過 ConcurrentLinkedQueue、AtomicInteger 等並發集合,我明白了:
小範圍共享資源 → 用 synchronized 就好,保護一個小區塊,不會造成大幅效能損耗。
整個資料結構需要多執行緒同時操作 → 直接用併發集合就能自動處理同步,寫程式更簡單,也不用擔心 race condition。
以前用 Future 收結果,要一個個 get() 等任務完成,常常要等很久,效率很低。現在用併發集合,任務完成就直接丟進 Queue,主程式最後統一取結果就好,順序雖然是任務完成的順序,但效率高很多。
今天我覺得自己對「多執行緒收集結果」有更直觀的理解了,也懂得該怎麼選擇工具:小區塊就鎖,大資料結構就用併發集合,必要時用 Atomic 變數保護統計。感覺寫起程式來會更安全又不拖慢效能,這個概念很實用。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言