Java parallel work iterator?

前端 未结 3 1371
后悔当初
后悔当初 2021-01-19 02:05

I\'m looking for a class where I can override a method to do the work, and return the results like an iterator. Something like this:

ParallelWorkIterator<         


        
相关标签:
3条回答
  • 2021-01-19 02:45

    Have a look at the ExecutorCompletionService. It does everything you want.

       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);
           }
       }
    

    The benefit of using a CompletionService is that it always returns the first completed result. This ensures you're not waiting for tasks to complete and it lets the uncompleted tasks run in the background.

    0 讨论(0)
  • 2021-01-19 02:46

    I would recommend looking at Java Executors.

    You submit a number of tasks and get a Future object back for each one. Your work is processed in the background, and you iterate through the Future objects (like you do in the above). Each Future returns a result as it become available (by calling get() - this blocks until the result has been generated in a separate thread)

    0 讨论(0)
  • 2021-01-19 02:52

    The closest thing I can think of is to use a CompletionService to accumulate results as they complete.

    Simple example:

    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.
    

    I would not recommend wrapping this behind an Iterator interface as the Future get() method can throw two possible checked exceptions: ExecutionException and InterruptedException, and you would therefore need to catch and either swallow these or rethrow them as RuntimeExceptions, neither of which is a very nice thing to do. In addition, your Iterator's hasNext() or next() methods would potentially need to block if there was a task in progress, which could be considered counterintuitive for clients using an Iterator. Instead I would implement my own more descriptive interface; e.g.

    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;
    }
    

    (Methods called take() typically represent a blocking call in the java.util.concurrent package).

    0 讨论(0)
提交回复
热议问题