2016-03-13 15 views
10

Khi nào thích LinkedBlockingQueue hơn ArrayBlockingQueue?Khi nào nên thích LinkedBlockingQueue trên ArrayBlockingQueue?

Những cấu trúc dữ liệu để sử dụng trong LinkedBlockingQueueArrayBlockingQueue khi:

  1. Bạn muốn một đọc hiệu quả và viết
  2. nên có dấu chân bộ nhớ ít

Mặc dù có một câu hỏi tương tự nhưng nó không làm nổi bật thực tế là nên được ưa thích?

Links:

Trả lời

18

Boris Spider đã vạch ra sự khác biệt rõ ràng nhất giữa ArrayBlockingQueueLinkedBlockingQueue - trước đây luôn bị chặn, trong khi sau đó có thể không bị chặn.

Vì vậy, trong trường hợp bạn cần một hàng đợi chặn không bị chặn, LinkedBlockingQueue hoặc LinkedTransferQueue được sử dụng làm BlockingQueue là các cược tốt nhất của bạn từ hộp công cụ java.util.concurrent.

Nhưng giả sử bạn cần hàng đợi chặn bị chặn. Cuối cùng, bạn nên chọn triển khai dựa trên thử nghiệm rộng rãi với mô phỏng khối lượng công việc trong thế giới thực của bạn. Tuy nhiên, sau đây là một số lưu ý có thể giúp bạn với sự lựa chọn của bạn hoặc với giải thích các kết quả từ các thí nghiệm:

  • ArrayBlockingQueue có thể được tạo ra với một cấu hình (on/off) Chính sách kế hoạch công bằng. Điều này là rất tốt nếu bạn cần sự công bằng hoặc muốn tránh sự đói kém của nhà sản xuất/người tiêu dùng, nhưng nó sẽ khiến bạn mất chi phí.
  • ArrayBlockingQueue phân bổ trước mảng sao lưu của nó, vì vậy nó không phân bổ các nút trong quá trình sử dụng, nhưng ngay lập tức lấy những gì có thể là một bộ nhớ đáng kể, có thể là vấn đề nếu bộ nhớ của bạn bị phân mảnh.
  • ArrayBlockingQueue nên có ít thay đổi về hiệu suất, vì nó có ít chi tiết hơn, nó sử dụng thuật toán đơn giản và ít phức tạp hơn, không tạo nút trong quá trình sử dụng và hành vi bộ nhớ cache của nó phải tương đối nhất quán.
  • LinkedBlockingQueue nên có thông lượng tốt hơn, vì nó sử dụng khóa riêng cho đầu và đuôi.
  • LinkedBlockingQueue không phân bổ trước các nút, điều đó có nghĩa là dấu vết bộ nhớ của nó gần bằng kích thước của nó, nhưng nó cũng có nghĩa là nó sẽ phát sinh một số công việc để phân bổ và giải phóng các nút.
  • LinkedBlockingQueue có thể sẽ có hành vi bộ nhớ cache tồi tệ hơn, điều này có thể ảnh hưởng đến hiệu suất của riêng nó, mà còn hiệu suất của các thành phần khác do chia sẻ sai.

Tùy thuộc vào tình huống sử dụng của bạn và bao nhiêu bạn quan tâm về hiệu suất, bạn cũng có thể muốn xem xét bên ngoài của java.util.concurrent và xem xét Disruptor (một đặc biệt nhanh, nhưng hơi chuyên giáp non-blocking vòng đệm) hoặc JCTools (một loạt các hàng đợi bị chặn hoặc không bị ràng buộc với các đảm bảo khác nhau tùy thuộc vào số lượng nhà sản xuất và người tiêu dùng).

+0

Câu trả lời hay! Tôi đồng ý với những gì bạn đã đề cập đến cũng tôi muốn nhấn mạnh (một lần nữa) thực tế là ArrayBlockingQueue được hỗ trợ bởi một mảng mà kích thước sẽ không bao giờ thay đổi sau khi tạo. Việc đặt công suất thành Integer.MAX_VALUE sẽ tạo ra một mảng lớn với chi phí cao trong không gian. ArrayBlockingQueue luôn bị chặn. LinkedBlockingQueue tạo các nút động cho đến khi đạt được dung lượng. Điều này là theo mặc định Integer.MAX_VALUE. Sử dụng công suất lớn như vậy không có thêm chi phí trong không gian. LinkedBlockingQueue được tùy chọn giới hạn. –

-1

Cả hai đều thực hiện BlockingQueue. Như tên cho thấy, arrayBlockingQueue được hỗ trợ bởi Array trong khi LinkedBlockingQueue được hỗ trợ bởi linked list.

Mà một trong những lựa chọn về cơ bản nên được giống như lý do để lựa chọn giữa một ArrayListLinkedList

Thêm một yếu tố để ArrayBlockingQueue được coi là nhanh hơn vì nó có nghĩa là chỉ thiết lập một tham chiếu đến một phần tử của sự ủng hộ Mảng đối tượng, trong khi thêm phần tử vào LinkedBlockingQueue có nghĩa là tạo một Node và đặt mục của nó là prevnext trường. Bên cạnh đó, khi chúng tôi xóa một phần tử khỏi LinkedBlockingQueue nút bị xóa trở thành rác có thể ảnh hưởng đến hiệu suất của ứng dụng.

+0

Đây chỉ là câu trả lời một phần, khác biệt chính là 'ArrayBlockingQueue' bị ràng buộc bởi một mảng ** kích thước cố định ** (sử dụng một mảng thực hiện vòng tròn). –

+0

@BoristheSpider, vui lòng kiểm tra lý do bổ sung. Ngoài điểm được chỉ định trong câu trả lời của bạn, các blockingQueues có cùng ý nghĩa như nhau đối với các cấu trúc dữ liệu cơ bản – Rahul

+0

Cấu trúc khóa của hai hàng đợi hoàn toàn khác nhau. So sánh cấu trúc bên trong của họ có phần không liên quan; bạn sẽ cần phải xem cấu trúc khóa nào so sánh tốt hơn trong môi trường đa luồng cụ thể của bạn - một nhà văn/nhiều độc giả, nhiều nhà văn/một người đọc, v.v. –

5

Từ JavaDoc for ArrayBlockingQueue

Một giáp chặn hàng đợi được hỗ trợ bởi là một mảng.

tôi nhấn mạnh

Từ JavaDoc for LinkedBlockingQueue:

Một tùy chọn-giáp chặn hàng đợi dựa trên các nút liên kết.

tôi nhấn mạnh

Vì vậy, nếu bạn cần một giáp đợi bạn có thể sử dụng, nếu bạn cần một hàng đợi vô biên bạn phải sử dụng LinkedBlockingQueue.

Đối với một số bị ràng buộc xếp hàng, khi đó bạn sẽ cần chuẩn để làm việc tốt hơn.

+0

Để có thể khai báo hàng đợi không bị ràng buộc cũng là một trong những lý do được chỉ định trong câu trả lời của tôi như linkedList là không bị chặn trong khi mảng không. – Rahul

+0

@rahulroc bạn thực sự không bao giờ nói điều đó chút nào và không bao giờ cung cấp bất kỳ bằng chứng nào cho xác nhận của bạn. Nói rằng một bộ sưu tập được hỗ trợ mảng bị ràng buộc cũng đơn giản và không đúng sự thật - một mảng 'ArrayList' được sao lưu. –

+0

Cảm ơn câu trả lời của bạn @BoristheSpider. Đúng vậy, đây là một lý do tốt cho sở thích, nhưng chúng tôi có sự khác biệt về hiệu suất khi: 1.Bạn muốn đọc và viết hiệu quả 2. không có sự lo ngại về việc hàng đợi có bị ràng buộc hay không 3. nên có dấu chân bộ nhớ ít hơn không? –

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