2015-06-08 14 views
6

Java có rất nhiều Bộ sưu tập khác nhau được thiết kế cho sự an toàn và an toàn luồng, và tôi thua lỗ để chọn lựa cho tình huống của mình.Danh sách hiệu quả nhất nhưng an toàn cho chủ đề/Bộ

Nhiều chủ đề có thể gọi .add().remove() và tôi sẽ sao chép danh sách này thường xuyên với một cái gì đó như List<T> newList = new ArrayList<T>(concurrentList). Tôi sẽ không bao giờ lặp lại danh sách đồng thời.

Tôi nghĩ về một cái gì đó như CopyOnWriteArrayList, nhưng tôi đã đọc rằng nó có thể rất kém hiệu quả vì bản thân nó tự sao chép mỗi khi nó được sửa đổi. Tôi hy vọng sẽ tìm thấy một sự thỏa hiệp tốt giữa an toàn và hiệu quả.

Danh sách hay (hoặc thiết lập) tốt nhất cho tình huống này là gì?

+1

Bạn có chắc là mình cần danh sách không? Bản đồ hoặc tập hợp có đáp ứng nhu cầu của bạn hay không. Việc truy cập đồng thời vào Bản đồ hoặc Tập hợp dễ dàng hơn nhiều so với danh sách. – bhspencer

+0

@bhspencer Có, tôi nghĩ một bộ có thể hoạt động. – RogueCSDev

+0

Nếu bạn thường chỉ thêm và xóa các phần tử ở cuối và bạn sao chép danh sách thường là cấu trúc dữ liệu hiệu quả nhất sẽ là danh sách liên kết đơn lẻ bất biến mà java không may không tích hợp nhưng đó là cấu trúc dữ liệu rất đơn giản để bạn có thể nhanh chóng tự mình thực hiện nó. – SpiderPig

Trả lời

1

Bạn có thể muốn xem xét liệu một ctrie sẽ là thích hợp đối với trường hợp sử dụng của bạn - nó có thread-safe addremove hoạt động, và "sao chép" (trong thực tế, tham gia một bản chụp của) các cấu trúc dữ liệu chạy trong thời gian O (1). Tôi biết hai triển khai JVM của cấu trúc dữ liệu: implementation one, implementation two.

3

Như @SpiderPig đã nói, trường hợp tốt nhất với List sẽ là danh sách không liên kết, được liên kết đơn lẻ.

Tuy nhiên, nhìn vào những gì đang được thực hiện ở đây, không cần List (nhận xét của @ bhspencer). Một ConcurrentSkipListSet sẽ hoạt động hiệu quả nhất (@augray).

Câu trả lời được chấp nhận của This Related Thread cung cấp thông tin chi tiết hơn về ưu và khuyết điểm của các bộ sưu tập đồng thời khác nhau.

+1

Lưu ý rằng một bộ đồng bộ cũng có một khóa toàn đối tượng (tất cả các cuộc gọi đến nó sẽ chặn để chỉ có một luồng có thể làm việc với nó tại một thời điểm). Nếu bạn có thể tìm cách sử dụng đối tượng đồng thời thay vì đối tượng đồng bộ, bạn sẽ có khả năng hoạt động hiệu quả hơn (tức là, giả sử rằng tài nguyên này tác động đến sự hoàn hảo, có vẻ như một giả thiết an toàn cho câu hỏi). – augray

+1

Nếu bạn sẵn sàng sử dụng một tập hợp, [ConcurrentSkipListSet] (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentSkipListSet.html) có thể sẽ hiệu quả hơn synchronizedSet. Từ * Java Concurrency in Practice *: "Thay thế các bộ sưu tập được đồng bộ hóa với các bộ sưu tập đồng thời có thể mang lại những cải tiến khả năng mở rộng đáng kể với ít rủi ro". – augray

0
Collections.newSetFromMap(new ConcurrentHashMap<...>()) 

Đây thường là cách thực hiện Bộ bình thường (HashSet thực sự là trình bao bọc được sửa đổi trên HashMap). Nó cung cấp cả lợi thế của hiệu suất/concurrecy từ ConcurrentHashMap, và không có thêm các tính năng như ConcurrentSkipListSet (đặt hàng), COW danh sách (sao chép mọi sửa đổi), hoặc hàng đợi đồng thời (FIFO/LIFO đặt hàng).

Chỉnh sửa: Tôi không thấy nhận xét của @ bhspencer trên bài đăng gốc, xin lỗi vì đã đánh cắp sự chú ý.

0

Hashset đang băm dựa trên sẽ tốt hơn Danh sách. Thêm cuối cùng và xóa đầu tiên sẽ tốt với LinkedList. Tìm kiếm sẽ nhanh chóng trong mảng danh sách đang được dựa trên chỉ mục mảng.

Xin cảm ơn,

Các vấn đề liên quan