2012-04-14 45 views
6

Trong dự án của tôi, tôi đang xây dựng một khung thực thi Java nhận các yêu cầu công việc từ một máy khách. Công việc (kích thước khác nhau) được chia nhỏ thành một tập hợp các tác vụ và sau đó được xếp hàng để xử lý. Có hàng đợi riêng biệt để xử lý từng loại tác vụ và mỗi hàng đợi được liên kết với một ThreadPool. ThreadPools được cấu hình theo cách sao cho hiệu suất tổng thể của động cơ là tối ưu.Work/Task Stealing ThreadPoolExecutor

Thiết kế này giúp chúng tôi cân bằng tải các yêu cầu có hiệu quả và yêu cầu lớn không kết thúc việc hogging tài nguyên hệ thống. Tuy nhiên đôi khi giải pháp trở nên không hiệu quả khi một số hàng đợi trống và hồ bơi chủ đề tương ứng của họ đang ngồi nhàn rỗi.

Để làm điều này tốt hơn, tôi đã nghĩ đến việc triển khai kỹ thuật đánh cắp công việc/nhiệm vụ để hàng đợi được tải nặng có thể nhận được sự trợ giúp từ các ThreadPool khác. Tuy nhiên điều này có thể yêu cầu thực hiện của riêng tôi Executor như Java không cho phép nhiều hàng đợi được liên kết với một ThreadPool và không hỗ trợ khái niệm ăn cắp công việc.

Đọc về Fork/Join nhưng điều đó dường như không phù hợp với nhu cầu của tôi. Bất kỳ đề xuất hoặc cách khác để xây dựng giải pháp này có thể rất hữu ích.

Cảm ơn Andy

+1

Bạn nên suy nghĩ về cách giữ cho tất cả các CPU bận rộn. Nó không quan trọng nếu một số chủ đề của bạn là nhàn rỗi nếu bạn đang sử dụng tốt nhất của CPU của bạn. –

+0

Nếu hồ bơi thread của bạn có nhiều chủ đề như bạn có cpus, bất kỳ hồ bơi thread cá nhân có thể "ăn cắp" tất cả các cpus ngay cả khi tất cả các hồ bơi thread khác đang nhàn rỗi. –

+0

@PeterLawrey - đó là sự thật, nhưng nếu có rất nhiều hồ bơi, sau đó bạn có thể có hiệu suất kém nếu tất cả các chủ đề trong tất cả các hồ đang làm việc cùng một lúc. – jtahlborn

Trả lời

1

bạn có thể thực hiện một cài đặt tùy chỉnh BlockingQueue (tôi nghĩ rằng bạn chủ yếu cần phải thực hiện các phương pháp offer()take()) được hỗ trợ bởi một hàng đợi "chính" và 0 hoặc thứ hơn hàng đợi. mất sẽ luôn luôn lấy từ hàng đợi sao lưu chính nếu không trống, nếu không nó có thể kéo từ hàng đợi thứ cấp.

thực tế, tốt hơn nên có 1 hồ bơi nơi tất cả công nhân có quyền truy cập vào tất cả các hàng đợi, nhưng "thích" một hàng đợi cụ thể. bạn có thể đưa ra tỷ lệ làm việc tối ưu của mình bằng cách gán các ưu tiên khác nhau cho các công nhân khác nhau. trong một hệ thống được nạp đầy đủ, công nhân của bạn phải làm việc với tỷ lệ tối ưu. trong một hệ thống bị tải xuống, công nhân của bạn sẽ có thể giúp đỡ với hàng đợi khác.

+0

Điều này có vẻ như là một ý tưởng hay mà tôi đang cố gắng thử với POC. –

2

Bạn đã xem số ForkJoinPool chưa? Framework fork-join được thực hiện theo kiểu mô-đun đẹp, do đó bạn chỉ có thể sử dụng pool thread đánh cắp công việc.

+1

Đọc API nhưng vẫn không thể tìm ra sự khác biệt của nó so với ThreadPoolExecutor thông thường. Có lẽ thiếu một số khía cạnh tốt hơn ở đó. –

+0

Vâng, tôi thấy, những gì bạn có trong thực tế, một sơ đồ phân vùng mà bây giờ bạn muốn làm cho linh hoạt - cho phép các ranh giới phân vùng thay đổi theo khối lượng công việc. "Làm việc ăn cắp" có thể là một thuật ngữ chuyên biệt hơn cho các đề án liên quan đến việc tạo hạt nhiệm vụ tốt - một nhiệm vụ thực hiện trên một luồng tạo ra các subtask và đẩy chúng vào deque riêng của nó để các chủ đề khác có thể lấy cắp công việc của nó. Vì vậy, có lẽ nếu bạn làm nghiên cứu theo thuật ngữ "phân vùng hồ bơi thread" bạn sẽ tìm thấy một cái gì đó phù hợp cho trường hợp của bạn. –

2

Java 8 có nhà máy và phương pháp tiện ích cho điều đó trong lớp học Executors. Có một thực hiện một hồ bơi thread ăn cắp công việc (here) mà, tôi tin rằng, là chính xác những gì bạn muốn.

+0

Chỉ có bất lợi tôi thấy với điều này là nó tạo ra ForkJoinThreads mới theo yêu cầu thay vì vay các chủ đề từ một hồ bơi toàn cầu - có thể là một hồ bơi chung hoặc một hồ bơi mà khách hàng có thể vượt qua. –

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