1) Việc CopyOnWriteArraySet
triển khai khá đơn giản - về cơ bản nó có một danh sách các phần tử trong một mảng và khi thay đổi danh sách, nó sao chép mảng. Lặp lại và các truy cập khác đang chạy tại thời điểm này tiếp tục với mảng cũ, tránh sự cần thiết phải đồng bộ hóa giữa người đọc và người viết (mặc dù bản thân văn bản cần phải được đồng bộ hóa). Các hoạt động thiết lập nhanh thông thường (đặc biệt contains()
) khá chậm ở đây, vì các mảng sẽ được tìm kiếm trong thời gian tuyến tính.
Chỉ sử dụng điều này cho các bộ thực sự nhỏ sẽ được đọc (lặp lại) thường xuyên và hiếm khi thay đổi. (Bộ nghe nhạc Swings sẽ là một ví dụ, nhưng đây không phải là bộ thực sự và chỉ nên được sử dụng từ EDT.)
2) Collections.synchronizedSet
sẽ chỉ đơn giản là bọc một khối đồng bộ hóa xung quanh mỗi phương thức của tập gốc. Bạn không nên truy cập trực tiếp vào bộ gốc. Điều này có nghĩa là không có hai phương thức nào của tập hợp có thể được thực thi đồng thời (một phương thức sẽ chặn cho đến khi kết thúc khác) - đây là an toàn luồng, nhưng bạn sẽ không có sự tương tranh nếu nhiều luồng thực sự sử dụng tập hợp. Nếu bạn sử dụng iterator, bạn vẫn cần phải đồng bộ hóa bên ngoài để tránh ConcurrencyModificationExceptions khi sửa đổi tập hợp giữa các lệnh gọi iterator. Hiệu suất sẽ giống như hiệu suất của bộ gốc (nhưng có một số chi phí đồng bộ hóa và chặn nếu được sử dụng đồng thời).
Sử dụng điều này nếu bạn chỉ có mức độ đồng thời thấp và muốn chắc chắn tất cả các thay đổi sẽ hiển thị ngay lập tức cho các luồng khác.
3) ConcurrentSkipListSet
là việc SortedSet
thực hiện đồng thời , với hầu hết các hoạt động cơ bản trong O (log n). Nó cho phép thêm / xóa đồng thời và đọc / lặp, trong đó phép lặp có thể hoặc không thể nói về những thay đổi kể từ khi trình lặp được tạo. Các hoạt động hàng loạt chỉ đơn giản là nhiều cuộc gọi đơn lẻ, và không phải là nguyên tử - các luồng khác chỉ có thể quan sát một số trong số chúng.
Rõ ràng bạn chỉ có thể sử dụng điều này nếu bạn có một số thứ tự tổng thể trên các yếu tố của bạn. Điều này trông giống như một ứng cử viên lý tưởng cho các tình huống đồng thời cao, cho các tập không quá lớn (vì O (log n)).
4) Đối với ConcurrentHashMap
(và Tập hợp có nguồn gốc từ nó): Ở đây, hầu hết các tùy chọn cơ bản là (trung bình, nếu bạn có tốt và nhanh hashCode()
) trong O (1) (nhưng có thể suy biến thành O (n)), như đối với HashMap / Hashset. Có một sự đồng thời hạn chế cho việc viết (bảng được phân vùng và quyền truy cập ghi sẽ được đồng bộ hóa trên phân vùng cần thiết), trong khi quyền truy cập đọc hoàn toàn đồng thời với chính nó và các luồng viết (nhưng có thể chưa thấy kết quả của các thay đổi hiện đang diễn ra bằng văn bản). Trình lặp có thể hoặc không thể thấy các thay đổi kể từ khi nó được tạo và các hoạt động hàng loạt không phải là nguyên tử. Thay đổi kích thước là chậm (như đối với HashMap / Hashset), do đó, hãy cố gắng tránh điều này bằng cách ước tính kích thước cần thiết khi tạo (và sử dụng thêm khoảng 1/3 số đó, vì nó thay đổi kích thước khi đầy 3/4).
Sử dụng công cụ này khi bạn có bộ lớn, hàm băm tốt (và nhanh) và có thể ước tính kích thước bộ và đồng thời cần thiết trước khi tạo bản đồ.
5) Có triển khai bản đồ đồng thời nào khác mà người ta có thể sử dụng ở đây không?