การเลือกรายการการทำงานพร้อมกันที่ดีที่สุดใน Java [ปิด]


101

เธรดพูลของฉันมีจำนวนเธรดคงที่ เธรดเหล่านี้จำเป็นต้องเขียนและอ่านจากรายการที่แชร์บ่อยๆ

ดังนั้นโครงสร้างข้อมูลใด (ควรเป็นรายการที่ดีกว่าต้องไม่มีการมอนิเตอร์) ในjava.util.concurrentแพ็คเกจจึงดีที่สุด


5
ขึ้นอยู่กับสิ่งที่คุณต้องการทำกับคอลเล็กชัน ดูโพสต์บล็อกของฉัน (แม้ว่าจะเกี่ยวกับ. Net แต่แนวคิดก็เหมือนกัน) คุณไม่น่าจะสามารถเขียนรหัสเธรดเซฟตี้ที่ถูกต้องด้วยไฟล์List.
SLaks

1
ตอนนี้ฉันใช้CopyOnWriteArrayListแต่ข้อยกเว้นConcurrentModificationExceptionยังคงถูกโยนทิ้งเป็นครั้งคราว
象嘉道

2
โปรดใส่ข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่คุณกำลังทำกับคอลเล็กชันเพื่อให้ผู้คนสามารถตอบได้ดีขึ้นมิฉะนั้นจะเป็นการคาดเดา
mattsh

2
ConcurrentModificationExceptionอาจได้มาจากปัญหาการประสาน; นอกจากนี้ยังเกิดขึ้นตัวอย่างเช่นในการวนซ้ำบนคอลเลกชันที่คุณพยายามลบองค์ประกอบออกจากคอลเลกชัน
toto2

1
ฉันรู้ว่ามันไม่ได้เป็นส่วนหนึ่งของแพ็กเกจ แต่มีคนลองใช้แล้วVectorหรือยัง?
WesternGun

คำตอบ:


100

จะดีกว่า List

เพียง Listการดำเนินการในการjava.util.concurrentเป็นCopyOnWriteArrayList นอกจากนี้ยังมีตัวเลือกของรายการที่ซิงโครไนซ์ตามที่ Travis Webb กล่าวถึง

ที่กล่าวมาคุณแน่ใจหรือว่าต้องการให้เป็นList? มีตัวเลือกมากขึ้นสำหรับQueues และ s พร้อมกันMap(และคุณสามารถสร้างSets จากMaps ได้) และโครงสร้างเหล่านั้นมักจะเหมาะสมที่สุดสำหรับสิ่งต่างๆหลายประเภทที่คุณต้องการทำกับโครงสร้างข้อมูลที่แชร์

สำหรับคิวคุณมีตัวเลือกมากมายและตัวเลือกใดเหมาะสมที่สุดขึ้นอยู่กับว่าคุณต้องใช้อย่างไร:


15
CopyOnWriteArrayListมีข้อเสียคือค่าเขียนแพงมาก (แต่ราคาถูกสำหรับการอ่าน) หากคุณเขียนจำนวนมากคุณควรใช้รายการที่ซิงโครไนซ์หรือคิว
Peter Lawrey

69

คอลเลกชัน Java ใด ๆ สามารถทำให้เธรดปลอดภัยได้ดังนี้:

List newList = Collections.synchronizedList(oldList);

หรือสร้างรายการที่ปลอดภัยสำหรับเธรดใหม่ล่าสุด:

List newList = Collections.synchronizedList(new ArrayList());

http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#synchronizedList(java.util.List)


7
ด้วยเหตุนี้คุณจะไม่พบการใช้งานรายการใน java.util.concurrent - อืมConcurrentHashMapแม้ว่าจะมีCollections.synchronizedMapวิธีการ
aioobe

7
อ่าน Javadocs ConcurrentHashMapบน รายละเอียดของการดำเนินการซิงโครไนซ์แตกต่างกัน โดยใช้synchronizedวิธีการCollectionsโดยทั่วไปเพียงแค่ห่อคลาสในจอภาพ Java ConcurrentHashMapใช้คุณสมบัติการทำงานพร้อมกันที่ชาญฉลาดยิ่งขึ้น
Travis Webb

1
ใช่. ถึงกระนั้นมันก็ทำให้ประโยคสุดท้ายของคุณไม่ถูกต้อง
aioobe

1
หากใช้มอนิเตอร์ประสิทธิภาพของโปรแกรมจะแย่มาก :-(
象嘉道

6
เพียงเพื่อเพิ่มการทำซ้ำใน newList จะไม่ปลอดภัยต่อเธรด !!
bluelurker

9

ถ้าขนาดของรายการถ้าแก้ไขแล้วคุณสามารถใช้AtomicReferenceArray สิ่งนี้จะช่วยให้คุณสามารถทำการอัพเดตที่จัดทำดัชนีไปยังสล็อตได้ คุณสามารถเขียนมุมมองรายการได้หากจำเป็น


7

ConcurrentLinkedQueueใช้คิวที่ไม่มีการล็อก (ตามคำแนะนำ CAS ที่ใหม่กว่า)


7
... ซึ่งไม่ใช้Listอินเทอร์เฟซ
aioobe

1
eSniff คุณจะดำเนินการList.set(int index, Object element)อย่างไรกับ ConcurrentLinkedQueue
John Vint

4
Listวิธีการเฉพาะส่วนใหญ่จะไม่สามารถนำไปใช้งานได้โดยใช้Queue(เช่นเพิ่ม / ตั้งค่าที่ดัชนีเฉพาะ) หรือสามารถจัดเรียงได้ แต่จะไม่มีประสิทธิภาพ (รับจากดัชนี) ฉันไม่คิดว่าคุณจะห่อได้จริงๆ ที่กล่าวว่าฉันคิดว่าคำแนะนำของ a Queueนั้นดีเนื่องจาก OP ไม่ได้อธิบายจริงๆว่าทำไมพวกเขาถึงต้องการไฟล์List.
ColinD

1
@ColinD นั่นคือคำตอบที่ฉันต้องการ มีเหตุผลที่ดีที่ไม่สามารถรวม CLQ ไว้ในรายการได้ แม้ว่าฉันจะเห็นด้วย แต่ไม่สามารถแยกแยะส่วนต่อประสานคิวได้
John Vint

1
❗️ที่น่าสังเกตว่า: "โปรดทราบว่าวิธีการปรับขนาดไม่เหมือนกับในคอลเลกชันส่วนใหญ่วิธีการกำหนดขนาดไม่ใช่การดำเนินการแบบคงที่เนื่องจากลักษณะแบบอะซิงโครนัสของคิวเหล่านี้การกำหนดจำนวนองค์ประกอบปัจจุบันจึงจำเป็นต้องมีการส่งผ่านองค์ประกอบ"
βξhrαng

6

คุณอาจต้องการดูConcurrentDoublyLinkedListเขียนโดย Doug Lea จาก "A Practical Lock-Free Doubly-Linked List" ของ Paul Martin ไม่ใช้อินเทอร์เฟซ java.util.List แต่มีวิธีการส่วนใหญ่ที่คุณจะใช้ในรายการ

ตาม javadoc:

การใช้งานรายการที่เชื่อมโยงพร้อมกันของ Deque (คิวสิ้นสุดสองครั้ง) การแทรกการลบและการเข้าถึงพร้อมกันจะดำเนินการอย่างปลอดภัยในหลายเธรด ตัวทำซ้ำมี ความสอดคล้องกันเล็กน้อยโดยส่งคืนองค์ประกอบที่สะท้อนสถานะของ deque ณ จุดใดจุดหนึ่งหรือตั้งแต่การสร้างตัววนซ้ำ พวกเขาไม่โยน ConcurrentModificationException และอาจดำเนินการควบคู่ไปกับการดำเนินการอื่น ๆ


3

หากตั้งค่าไว้เพียงพออาจใช้ConcurrentSkipListSet (การใช้งานจะขึ้นอยู่กับConcurrentSkipListMapซึ่งใช้ข้ามรายการ )

ต้นทุนเวลาเฉลี่ยที่คาดไว้คือ log (n) สำหรับการดำเนินการมีเพิ่มและลบ วิธีการกำหนดขนาดไม่ใช่การดำเนินการตลอดเวลา


แต่มันถูกตั้งค่าไม่อยู่ในรายการ คุณไม่สามารถเพิ่มวัตถุที่มี hashcod emultiple เดียวกันได้
Tuğrul Karakaya

นั่นคือเหตุผลที่ฉันเขียนว่า: "If set is
enough
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.