2013-01-10 16 views
5

Tôi đang sử dụng Executors.newCachedThreadPool()invokeAll với Danh sách Callable s để thực hiện xử lý đa luồng chạy dài. Chủ đề chính của tôi bị chặn cho đến khi tất cả các chủ đề đã kết thúc và tôi có thể xử lý tương lai được trả lại bằng invokeAll. Tuy nhiên, tôi muốn invokeAll trả lại ngay lập tức nếu một trong số Callable s ném một ngoại lệ và chấm dứt các chủ đề khác.Quay lại chủ đề chính ngay sau khi một chủ đề con ném một ngoại lệ

Sử dụng execute thay vì invokeAll sẽ chặn trên số future.get() đầu tiên không cần phải là thao tác ném thực thi.

Sử dụng chờ đợi bận rộn để lặp qua tất cả các tương lai và kiểm tra isDone() dường như cũng không phải là cách tốt nhất.

+0

bạn đã thử tắt dịch vụ thi hành và có làm gián đoạn các tác vụ khác không? nếu những nhiệm vụ khác không chờ đợi/đọc họ vẫn có thể kiểm tra cờ gián đoạn thread mỗi bây giờ và sau đó – radai

Trả lời

6

Bạn có thể sử dụng các cơ chế đồng bộ hóa phức tạp hơn như chốt, rào cản hoặc semaphores, nhưng hãy xem ExecutorCompletionService. Đó là một wrapper nhẹ khoảng ExecutorService cho phép bạn nghe nhiệm vụ hoàn thành đầu tiên. Dưới đây là ví dụ nhanh:

final ExecutorService executorService = Executors.newCachedThreadPool(); 
final ExecutorCompletionService<String> completionService = 
      new ExecutorCompletionService<String>(executorService); 
for (int i = 0; i < 10; ++i) { 
    completionService.submit(new Task()); 
} 
completionService.take().get(); 

Mã này khá đơn giản. Trước tiên, bạn quấn executorService với completionService. Sau đó bạn sử dụng nó để gửi nhiệm vụ cái khác. Dòng cuối cùng là rất quan trọng. Nhiệm vụ đầu tiên đã hoàn thành và cố gắng lấy kết quả. Nếu nó ném một ngoại lệ, nó sẽ được rethrown đây, được bao bọc bởi ExecutionException:

try { 
    completionService.take().get(); 
} catch (ExecutionException e) { 
    e.getCause();  //this was thrown from task! 
} 

Bên catch khối bạn bằng cách nào đó có thể xử lý các ngoại lệ, ví dụ hủy các tác vụ còn lại hoặc tắt toàn bộ nhóm luồng.

Tất nhiên bạn được tự do chờ tất cả công việc hoàn thành bằng cách gọi take() mười lần. Mỗi cuộc gọi sẽ chặn miễn là có ít nhất một tác vụ đã hoàn thành.

+0

+1 bạn giành chiến thắng này ;-) – assylias

+0

Và làm thế nào bạn sẽ chấm dứt phần còn lại của các chủ đề khi ngoại lệ? –

+0

@zaske: mỗi 'submit()' trả về 'Tương lai '. Nếu bạn gặp phải một ngoại lệ, bạn có thể lặp lại tất cả các tương lai và 'cancel()' chúng. –