Итератор работы параллели Java?

Ключевое слово события в c# изменяет объявление делегата. Это предотвращает прямое присвоение на делегата (можно только использовать + = и - = на событии), и это предотвращает вызов делегата снаружи класса.

, Таким образом, Вы могли изменить свой код для сходства с этим:

public class CustomGUIElement
{
...
    public MouseEventHandler Click;
    // etc, and so forth.
...
}

Тогда можно вызвать событие снаружи класса как это.

myCustomGUIElement.Click(sender,args);

недостаток состоит в том, что код с помощью класса может перезаписать любые зарегистрированные обработчики очень легко с кодом как это:

myCustomGUIElement.Click = null;

, который не позволяется, если делегат Щелчка объявляется как событие.

5
задан job 4 August 2009 в 16:09
поделиться

3 ответа

Посмотрите на ExecutorCompletionService . Он делает все, что вы хотите.

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

Преимущество использования CompletionService заключается в том, что он всегда возвращает первый завершенный результат. Это гарантирует, что вы не дожидаетесь завершения задач, и позволяет незавершенным задачам работать в фоновом режиме.

13
ответ дан 18 December 2019 в 10:47
поделиться

Я бы порекомендовал посмотреть на Java Executors .

Вы отправляете несколько задач и для каждой из них получаете объект Future . Ваша работа обрабатывается в фоновом режиме, и вы перебираете объекты Future (как в приведенном выше примере). Каждое будущее возвращает результат, когда он становится доступным (путем вызова get () - это блокируется, пока результат не будет сгенерирован в отдельном потоке)

2
ответ дан 18 December 2019 в 10:47
поделиться

Самое близкое, что я могу придумать, - это использовать CompletionService для накопления результатов по мере их завершения.

Простой пример:

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.

Я бы не рекомендовал упаковывать это за интерфейсом Iterator , поскольку метод Future get () может выдавать два возможных отмеченных исключения: ExecutionException и InterruptedException , и поэтому вам нужно будет поймать и либо проглотить их, либо повторно выбросить как RuntimeException , ни то, ни другое не очень хорошо. Кроме того, ваши методы Iterator hasNext () или next () потенциально должны блокироваться, если выполнялась задача, что может показаться нелогичным для клиентов, использующих итератор . Вместо этого я бы реализовал свой собственный более наглядный интерфейс; например

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

(методы, называемые take () , обычно представляют собой блокирующий вызов в пакете java.util.concurrent ).

1
ответ дан 18 December 2019 в 10:47
поделиться