Опрос нескольких потоков и загрузка процессора - PullRequest
1 голос
/ 21 августа 2011

У меня есть вызов, который получает список заданий от пользователя, скажем, пользователь отправил 3 задания A, B и C, все они начинают выполнение в своих собственных потоках AT, BT и CT, затем я начинаю отслеживать эти 3 потока, если Сбой одного из заданий, скажем, Б не удалось, мне нужно дать сигнал А и С остановиться. Когда все потоки остановлены, возвращаются, когда все завершается успешно, если один - ложь.

В настоящее время у меня есть один большой цикл while, который выполняет проверку и спит в течение 50 мс. Это работает, но мне было интересно, что есть лучший способ сделать это без какого-либо сна, я пробовал спать 0 мс. до конца очереди процессора, но она по-прежнему использует слишком много процессора около 60%.

Ответы [ 3 ]

3 голосов
/ 21 августа 2011

Это звучит как вариант использования для ExecutorCompletionService

// wrap tasks A, B and C into runnables (or callables if you need some result):
Callable<Result> taskA = ...;
Callable<Result> taskB = ...;
Callable<Result> taskC = ...;

// create an ExecutorCompletionService
// to which you must pass an ExecutorService
// (choose one according to your precise use case)
// (the newCachedThreadPoolExecutor might not be a sensible choice)
ExecutorCompletionService e = new ExecutorCompletionService(Executors.newCachedThreadPoolExecutor());

Set<Future<Result>> futures = new HashSet<>();

// submit your tasks:
futures.add(e.submit(taskA));
futures.add(e.submit(taskB));
futures.add(e.submit(taskC));

// now call take() on the executor completion service,
// which will block the calling thread until the first task has completed
// either succesfully or abruptly (with an exception)
Future<Result> f = e.take();

После этого, когда вы звоните f.get(), вы получите либо экземпляр Result, либовыдаст ExectutionException (обёртывание исключения, выданного исполнением).Любая из них произойдет немедленно (благодаря службе завершения исполнителя).

Тогда вы будете реагировать соответственно: если f.get() выдает исключение, удалите f из набора futures, итерируйте по другим элементамнабора (то есть с помощью других заданий, которые вы представили) и .cancel() их.Callable должны быть закодированы для отмены, в противном случае вызов .cancel() ничего не сделает.

0 голосов
/ 21 августа 2011

Вы можете добавить обратный вызов к заданиям, который вызывается в случае сбоя потока. Затем обратный вызов продолжит останавливать все потоки.

0 голосов
/ 21 августа 2011

Вы можете обернуть задания A, B, C в Runnable, который знает, когда задание не удалось, а также знает об управляющем потоке. Когда эта оболочка обнаруживает, что задание не выполнено (исключение, условия выполнения и что нет), оно уведомляет управляющий поток о дальнейших действиях.

Таким образом, вам не придется опрашивать потоки, но вы будете ждать сигнала от детектора ошибок оболочки.

...