2008-12-11 39 views
16

Tôi nghĩ rằng tôi sẽ điều chỉnh lại câu hỏi của mình từBạn nên sử dụng BlockingQueue Implementations thay vì triển khai hàng đợi đơn giản ở đâu?

Bạn nên sử dụng BlockingQueue Triển khai thay vì triển khai hàng đợi đơn giản ở đâu?

để

gì được những ưu điểm/nhược điểm của BlockingQueue qua triển khai Queue có tính đến các khía cạnh xem xét như tốc độ, đồng thời hoặc các tài sản khác mà khác nhau ví dụ thời gian để truy cập phần tử cuối cùng.

Tôi đã sử dụng cả hai loại Hàng đợi. Tôi biết rằng Hàng đợi Chặn thường được sử dụng trong ứng dụng đồng thời. Tôi đã viết đơn giản ByteBuffer hồ bơi, nơi tôi cần một số giữ chỗ cho các đối tượng ByteBuffer. Tôi cần nhanh nhất, thực hiện hàng đợi an toàn luồng. Thậm chí có các danh sách triển khai Danh sách như ArrayList có thời gian truy cập liên tục cho các phần tử.

Mọi người có thể thảo luận về ưu và khuyết điểm của việc thực thi BlockingQueue vs Queue vs List không?

Hiện tại tôi đã sử dụng ArrayList để giữ các đối tượng ByteBuffer này.

Tôi sẽ sử dụng cấu trúc dữ liệu nào để giữ các đối tượng này?

Trả lời

26

Công suất hạn chế BlockingQueue cũng hữu ích nếu bạn muốn điều chỉnh một số loại yêu cầu. Với hàng đợi không bị chặn, một nhà sản xuất có thể vượt xa người tiêu dùng. Các nhiệm vụ cuối cùng sẽ được thực hiện (trừ khi có quá nhiều thứ mà chúng gây ra một số OutOfMemoryError), nhưng nhà sản xuất có thể từ lâu đã từ bỏ, vì vậy nỗ lực bị lãng phí.

Trong các trường hợp như vậy, có thể tốt hơn là báo hiệu nhà sản xuất sẽ là hàng đợi đầy, và từ bỏ nhanh chóng với lỗi. Ví dụ, nhà sản xuất có thể là một yêu cầu web, với người dùng không muốn chờ đợi quá lâu, và mặc dù nó sẽ không tiêu tốn nhiều chu kỳ CPU trong khi chờ đợi, nó đang sử dụng hết tài nguyên giới hạn như ổ cắm và một số bộ nhớ . Từ bỏ sẽ cung cấp cho các nhiệm vụ đã được xếp hàng đợi đã là một cơ hội tốt hơn để hoàn thành một cách kịp thời.


Về câu hỏi được sửa đổi, tôi giải thích là "Bộ sưu tập tốt để giữ đồ vật trong hồ bơi là gì?"

Số LinkedBlockingQueue không bị chặn là một lựa chọn tốt cho nhiều hồ bơi. Tuy nhiên, tùy thuộc vào chiến lược quản lý hồ bơi của bạn, một ConcurrentLinkedQueue cũng có thể hoạt động.

Trong ứng dụng tổng hợp, chặn "đặt" không phù hợp. Kiểm soát kích thước tối đa của hàng đợi là công việc của người quản lý hồ bơi — nó quyết định khi nào tạo hoặc phá hủy tài nguyên cho nhóm. Khách hàng của hồ bơi mượn và trả lại tài nguyên từ hồ bơi. Thêm một đối tượng mới hoặc trả về một đối tượng mượn trước đó vào hồ bơi phải là các hoạt động nhanh, không chặn. Vì vậy, một hàng đợi dung lượng bị ràng buộc không phải là một lựa chọn tốt cho các hồ bơi.

Mặt khác, khi truy xuất đối tượng từ nhóm, hầu hết các ứng dụng muốn đợi cho đến khi tài nguyên có sẵn. Một hoạt động "lấy" chặn ít nhất là tạm thời, hiệu quả hơn nhiều so với "chờ đợi bận rộn" — nhiều lần bỏ phiếu cho đến khi tài nguyên có sẵn. LinkedBlockingQueue là một lựa chọn tốt trong trường hợp này. Người vay có thể chặn vô thời hạn với take hoặc giới hạn thời gian mà người đó sẵn sàng chặn với poll.

Trường hợp ít phổ biến hơn khi khách hàng không sẵn lòng chặn, nhưng có khả năng tự tạo tài nguyên nếu nhóm trống. Trong trường hợp đó, ConcurrentLinkedQueue là một lựa chọn tốt. Đây là một khu vực màu xám, nơi tốt nhất nên chia sẻ tài nguyên (ví dụ: bộ nhớ) càng nhiều càng tốt, nhưng tốc độ thậm chí còn quan trọng hơn. Trong trường hợp tồi tệ hơn, điều này làm thoái hóa tất cả các luồng có thể hiện riêng của tài nguyên; sau đó nó sẽ có hiệu quả hơn không bận tâm cố gắng chia sẻ giữa các chủ đề.

Cả hai bộ sưu tập này đều mang lại hiệu suất tốt và dễ sử dụng trong một ứng dụng đồng thời. Đối với các ứng dụng không đồng thời, ArrayList khó đánh bại. Ngay cả đối với các bộ sưu tập phát triển động, chi phí trên mỗi phần tử của một LinkedList cho phép ArrayList với một số vị trí trống để luôn cạnh tranh về trí nhớ.

+1

Cảm ơn Erickson cho một lời giải thích thoải mái như vậy. Nó đã giải quyết được vấn đề của tôi. –

2

Bạn sẽ thấy BlockingQueue trong các tình huống đa luồng. Ví dụ: bạn cần chuyển số BlockingQueue làm tham số để tạo ThreadPoolExecutor nếu bạn muốn tạo một tham số bằng hàm tạo. Tùy thuộc vào loại hàng đợi bạn vượt qua trong người thi hành có thể hành động khác nhau.

0

BlockingQueue cũng hữu ích cho việc tuần tự hóa các hoạt động song song phụ thuộc lẫn nhau.

Để mang lại một bê tông (mặc dù hơi tùy ý) Ví dụ, here là một thử nghiệm song song trong một thời gian thực kiên nhẫn đợi ứng dụng web mà callInPatient() cần khởi chạy song song với registerPatientToAppointment(), nhưng cần phải đợi cho đến khi registerPatientToAppointment() được hoàn thành trước khi thực hiện callPatientInAtDoctorsOffice() :

public class ClinicPatientQueueAppTest extends ParallelTest { 

    private static final BlockingQueue WAIT_FOR_REGISTRATION_QUEUE = new ArrayBlockingQueue(2); 

    @Test 
    public void callInPatient() { 
     loginToDoctorsOffice("user", "password"); 
     waitUntilRegistrationCompleted(); // <-- 
     callPatientInAtDoctorsOffice(); 
    } 

    @Test 
    public void registerPatientToAppointment() { 
     registerPatientAtRegistrationKiosk("Patient Peter"); 
     notifyRegistrationCompleted(); // <-- 
    } 

    private void waitUntilRegistrationCompleted() { 
     WAIT_FOR_REGISTRATION_QUEUE.take(); 
    } 

    private void notifyRegistrationCompleted() { 
     WAIT_FOR_REGISTRATION_QUEUE.put(this); 
    } 

} 
0

đó là một thực hiện Queue hỗ trợ bổ sung hoạt động mà

chờ đợi xếp hàng để trở thành không trống khi lấy một phần tử,

chờ đợi cho không gian trở nên có sẵn trong hàng đợi khi lưu trữ một yếu tố .

Nếu bạn yêu cầu trên chức năng sẽ được thực hiện tiếp theo Queue của bạn sau đó sử dụng Blocking Queue

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