Chọn danh sách đồng thời tốt nhất trong Java [đã đóng]


98

Nhóm chủ đề của tôi có một số lượng chủ đề cố định. Các chủ đề này cần phải viếtđọc từ một danh sách được chia sẻ thường xuyên.

Vì vậy, cấu trúc dữ liệu nào (tốt hơn là một Danh sách, phải không có màn hình) trong java.util.concurrentgói là tốt nhất trong trường hợp này?


5
Điều đó phụ thuộc vào những gì bạn muốn làm với bộ sưu tập. Xem bài đăng trên blog của tôi (mặc dù là về .Net, các khái niệm đều giống nhau). Bạn không chắc có thể viết đúng mã an toàn chuỗi với một List.
SLaks

1
Bây giờ, tôi đang sử dụng CopyOnWriteArrayList , nhưng ngoại lệ ConcurrentModificationException thỉnh thoảng vẫn bị ném ra.
象 嘉 道

2
Vui lòng bao gồm thêm thông tin về những gì bạn đang làm với bộ sưu tập để mọi người có thể trả lời tốt hơn, nếu không, đó chỉ là phỏng đoán.
mattsh

2
Điều này ConcurrentModificationExceptioncó thể không đến từ sự cố đồng bộ hóa; nó cũng phát sinh ví dụ như trong vòng lặp for qua một tập hợp mà bạn cố gắng xóa một phần tử khỏi tập hợp.
toto2

1
Tôi biết nó không phải là một phần của gói, nhưng ai đó đã thử Vectorchưa?
WesternGun

Câu trả lời:


96

tốt hơn nên List

Việc triển khai duy nhấtCopyOnWriteArrayList . Ngoài ra còn có tùy chọn danh sách đồng bộ như Travis Webb đề cập.Listjava.util.concurrent

Điều đó nói rằng, bạn có chắc bạn cần nó là một List? Có nhiều lựa chọn hơn cho Queuecác s và s đồng thời Map(và bạn có thể tạo Settừ Mapcác s), và các cấu trúc đó có xu hướng hợp lý nhất đối với nhiều kiểu bạn muốn làm với cấu trúc dữ liệu dùng chung.

Đối với hàng đợi, bạn có rất nhiều tùy chọn và tùy chọn nào phù hợp nhất tùy thuộc vào cách bạn cần sử dụng nó:


14
CopyOnWriteArrayListcó nhược điểm là rất tốn kém khi ghi (nhưng rẻ khi đọc) Nếu bạn thực hiện nhiều ghi, tốt hơn hết bạn nên sử dụng Danh sách đồng bộ hoặc một hàng đợi.
Peter Lawrey

67

Bất kỳ bộ sưu tập Java nào cũng có thể được tạo thành Thread-safe như sau:

List newList = Collections.synchronizedList(oldList);

Hoặc để tạo một danh sách an toàn theo chuỗi hoàn toàn mới:

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

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


7
Vì lý do này, bạn sẽ không tìm thấy danh sách triển khai trong java.util.concurrent - Uhm, ConcurrentHashMapmặc dù có một Collections.synchronizedMapphương pháp.
aioobe

7
Đọc Javadocs trên ConcurrentHashMap. Các chi tiết của việc triển khai đồng bộ hóa là khác nhau. sử dụng các synchronizedphương thức Collectionsvề cơ bản chỉ bao bọc lớp trong một màn hình Java. ConcurrentHashMapsử dụng các tính năng đồng thời thông minh hơn.
Travis Webb

1
Vâng. Tuy nhiên, nó làm cho câu cuối cùng của bạn không hợp lệ.
aioobe

1
Nếu sử dụng màn hình, hiệu suất của chương trình thực sự rất tệ :-(
象 嘉 道

5
Chỉ cần thêm, việc lặp lại trên newList không an toàn cho chuỗi. !!
bluelurker

9

Nếu kích thước của danh sách nếu được cố định, thì bạn có thể sử dụng AtomicReferenceArray . Điều này sẽ cho phép bạn thực hiện các cập nhật được lập chỉ mục cho một vị trí. Bạn có thể viết dạng xem Danh sách nếu cần.


6

Bạn có thể muốn xem ConcurrentDoublyLinkedList được viết bởi Doug Lea dựa trên "A Practical Lock-Free-Linked List" của Paul Martin. Nó không triển khai giao diện java.util.List, nhưng cung cấp hầu hết các phương pháp bạn sẽ sử dụng trong một Danh sách.

Theo javadoc:

Triển khai danh sách liên kết đồng thời của Deque (hàng đợi kết thúc kép). Các hoạt động chèn, loại bỏ và truy cập đồng thời thực thi một cách an toàn trên nhiều luồng. Các trình lặp là nhất quán yếu , trả về các phần tử phản ánh trạng thái của deque tại một số thời điểm tại hoặc kể từ khi tạo trình lặp. Họ không ném ConcurrentModificationException và có thể tiến hành đồng thời với các hoạt động khác.


5

ConcurrentLinkedQueuesử dụng hàng đợi không có khóa (dựa trên lệnh CAS mới hơn ).


7
... mà không triển khai Listgiao diện.
aioobe

1
eSniff, bạn sẽ triển khai List.set(int index, Object element)với ConcurrentLinkedQueue như thế nào?
John Vint,

4
Hầu hết các Listphương pháp-cụ thể hoặc sẽ không thể thực hiện được bằng cách sử dụng Queue(ví dụ: thêm / đặt tại một chỉ mục cụ thể) hoặc có thể được thực hiện nhưng sẽ không hiệu quả (lấy từ một chỉ mục). Vì vậy, tôi không nghĩ bạn có thể thực sự quấn nó. Điều đó nói rằng, tôi nghĩ rằng gợi ý về một Queuelà tốt vì OP chưa thực sự giải thích tại sao họ cần một List.
ColinD

1
@ColinD đó là câu trả lời mà tôi muốn. Có những lý do chính đáng khiến CLQ không thể được đưa vào một Danh sách. Mặc dù tôi đồng ý, nhưng không thể loại trừ giao diện Hàng đợi.
John Vint,

1
❗️ Cần lưu ý rằng: "Hãy
Behrang Saeedzadeh

3

Nếu đặt là đủ, ConcurrentSkipListSet có thể được sử dụng. (Việc triển khai nó dựa trên ConcurrentSkipListMap thực hiện một danh sách bỏ qua .)

Chi phí thời gian trung bình dự kiến ​​là log (n) cho các hoạt động chứa, thêm và loại bỏ; phương pháp kích thước không phải là một hoạt động thời gian cố định.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.