2009-08-04 42 views
5

Tôi đang tìm một lớp mà tôi có thể ghi đè phương thức để thực hiện công việc và trả lại kết quả như một trình lặp. Một cái gì đó như thế này:Java iterator công việc song song?

ParallelWorkIterator<Result> itr = new ParallelWorkIterator<Result>(trials,threads) { 

    public Result work() { 
    //do work here for a single trial... 
    return answer; 
    } 

}; 
while (itr.hasNext()) { 
    Result result = itr.next(); 
    //process result... 
} 

Điều này chủ yếu sẽ được sử dụng cho những thứ như mô phỏng monte carlo, nhưng tôi không muốn phải đối phó với việc thiết lập hồ bơi chủ đề và quản lý các chủ đề trả về mỗi lần. Tôi đã cuộn lớp của riêng mình rằng hy vọng hoàn thành điều này, nhưng tôi không đủ tự tin và nghĩ rằng tôi sẽ kiểm tra xem có điều gì đó như thế này đã tồn tại chưa.

Chỉnh sửa: Để rõ ràng, tôi muốn nó tiếp tục chạy dưới nền và xếp hàng đợi kết quả sau mỗi phương thức công việc sẽ trả về cho đến khi tất cả các thử nghiệm đã được hoàn thành. Vì vậy, các phương pháp tiếp theo có thể chờ đợi để trở lại cho đến khi có một kết quả trong hàng đợi.

Trả lời

12

Hãy xem qua số ExecutorCompletionService. Nó làm mọi thứ bạn muốn.

void solve(Executor e, Collection<Callable<Result>> solvers) 
    throws InterruptedException, ExecutionException { 
     //This class will hold and execute your tasks 
     CompletionService<Result> ecs 
      = new ExecutorCompletionService<Result>(e); 
     //Submit (start) all the tasks asynchronously 
     for (Callable<Result> s : solvers) 
      ecs.submit(s); 
     //Retrieve completed task results and use them 
     int n = solvers.size(); 
     for (int i = 0; i < n; ++i) { 
      Result r = ecs.take().get(); 
      if (r != null) 
       use(r); 
     } 
    } 

Lợi ích của việc sử dụng dịch vụ hoàn thành là nó luôn trả về kết quả đầu tiên hoàn thành. Điều này đảm bảo bạn không chờ đợi các tác vụ hoàn thành và nó cho phép các tác vụ chưa hoàn thành chạy trong nền.

+0

Cảm ơn, có vẻ như mọi thứ tôi muốn. Tôi chỉ muốn java không quá chi tiết. – job

+3

tiết và rõ ràng là một nửa thanh kiếm hai lưỡi. –

+0

Những gì tôi đã làm để xử lý verbosity là viết một lớp bao bọc kéo dài ExecutorCompletionService, và giữ một danh sách các tương lai đã gửi. Boolean hasRemaining() {return 0 Tim

2

Tôi khuyên bạn nên xem xét Java Executors.

Bạn gửi một số tác vụ và nhận lại đối tượng Future cho từng đối tượng. Công việc của bạn được xử lý ở chế độ nền và bạn lặp qua các đối tượng Tương lai (giống như bạn làm ở trên). Mỗi tương lai trả về kết quả khi nó có sẵn (bằng cách gọi get() - khối này cho đến khi kết quả được tạo trong một chủ đề riêng biệt)

1

Điều gần nhất tôi có thể nghĩ là sử dụng CompletionService để tích lũy kết quả khi chúng hoàn tất.

ví dụ đơn giản:

ExecutorService executor = Executors.newSingleThreadExecutor(); // Create vanilla executor service. 
CompletionService<Result> completionService = new ExecutorCompletionService<Result>(executor); // Completion service wraps executor and is notified of results as they complete. 
Callable<Result> callable = new MyCallable(); 

executor.submit(callable); // Do not store handle to Future here but rather obtain from CompletionService when we *know* the result is complete. 

Future<Result> fut = completionService.take(); // Will block until a completed result is available. 
Result result = fut.get(); // Will not block as we know this future represents a completed result. 

tôi sẽ không khuyên bạn nên gói này đằng sau một giao diện Iterator như Futureget() phương pháp có thể ném hai trường hợp ngoại lệ được kiểm tra khả năng: ExecutionExceptionInterruptedException, và do đó bạn sẽ cần phải bắt và hoặc nuốt những điều này hoặc rethrow chúng như RuntimeException s, không phải là một điều rất tốt đẹp để làm. Ngoài ra, các phương pháp hoặc next() của bạn có khả năng sẽ cần chặn nếu có một công việc đang được tiến hành, có thể được coi là không trực quan đối với khách hàng sử dụng Iterator. Thay vào đó, tôi sẽ thực hiện giao diện mô tả của riêng mình hơn; ví dụ.

public interface BlockingResultSet { 
    /** 
    * Returns next result when it is ready, blocking is required. 
    * Returns null if no more results are available. 
    */ 
    Result take() throws InterruptedException, ExecutionException; 
} 

(phương pháp gọi là take() thường đại diện cho một cuộc gọi chặn trong gói java.util.concurrent).

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