Понимание будущего / резьбы
-
26-09-2019 - |
Вопрос
Я пытаюсь использовать фьючерсы в первый раз. Кажется умным, что вы можете отменить работу, но она не работает должным образом. В приведенном ниже примере ниже, только первая задача отменяется. Остальные завершены. Я неправильно понял использование фьючерсов?
public class ThreadExample
{
public static void main(String[] args) throws InterruptedException, ExecutionException
{
int processors = Runtime.getRuntime().availableProcessors();
System.out.println("Processors: " + processors);
ExecutorService es = Executors.newFixedThreadPool(processors);
int nowork = 10;
Future<Integer>[] workres = new Future[nowork];
for(int i = 0; i < nowork; i++)
{
workres[i] = es.submit(new SomeWork(i));
}
for(int i = 0; i < nowork; i++)
{
if(i % 2 == 0)
{
System.out.println("Cancel");
workres[i].cancel(true);
}
if(workres[i].isCancelled())
{
System.out.println(workres[i] + " is cancelled");
}
else
{
System.out.println(workres[i].get());
}
}
es.shutdown();
}
}
class SomeWork implements Callable<Integer>
{
private int v;
public SomeWork(int v)
{
this.v = v;
}
@Override
public Integer call() throws Exception
{
TimeUnit.SECONDS.sleep(5);
System.out.println(v + " done at " + (new Date()));
return v;
}
}
Выход:
Processors: 4
Cancel
java.util.concurrent.FutureTask@10d448 is cancelled
4 done at Wed May 12 17:47:05 CEST 2010
2 done at Wed May 12 17:47:05 CEST 2010
1 done at Wed May 12 17:47:05 CEST 2010
3 done at Wed May 12 17:47:05 CEST 2010
1
Cancel
2
3
Cancel
4
5 done at Wed May 12 17:47:10 CEST 2010
7 done at Wed May 12 17:47:10 CEST 2010
8 done at Wed May 12 17:47:10 CEST 2010
6 done at Wed May 12 17:47:10 CEST 2010
5
Cancel
6
7
Cancel
8
9 done at Wed May 12 17:47:15 CEST 2010
9
Решение
Проблема в том, что ваша петля отмены перекрывается с вашим get()
петля, какие блоки. Я думаю, вы хотите иметь 2 петель, не так ли? Одна петля, которая отменяет даже пронумерованные задания, а затем вторая петля, которая проверяет, какие из них отменены, а какие нет, а затем get()
соответственно.
То, как он сейчас написан, до того, как петли даже имел возможность отменить workres[2]
, он проверил и попросил get()
от workres[1]
.
Так что я думаю, что вам нужно 3 этапа:
1. The `submit()` loop
2. The selective `cancel()` loop
3. The selective `get()` loop (which blocks)
Другие советы
То Future#cancel()
не прекратит / прерывает уже работает рабочие места. Это будет отменить только не выполненные рабочие места.
Обновлять: Полигенераторы прибиты корневой причиной вниз (+1): вот улучшенный код:
int processors = Runtime.getRuntime().availableProcessors();
System.out.println("Processors: " + processors);
ExecutorService es = Executors.newFixedThreadPool(processors);
int nowork = 10;
Future<Integer>[] workers = new Future[nowork];
for (int i = 0; i < nowork; i++) {
final int ii = i;
workers[i] = es.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return ii;
}
});
}
for (int i = 0; i < nowork; i++) {
if (i % 2 == 0) {
System.out.println("Cancel worker " + i);
workers[i].cancel(true);
}
}
for (int i = 0; i < nowork; i++) {
if (workers[i].isCancelled()) {
System.out.println("Worker " + i + " is cancelled");
} else {
System.out.println("Worker " + i + " returned: " + workers[i].get());
}
}
es.shutdown();
Результат:
Процессоры: 2 Отмена Работник 0 Отмена Работник 2 Отмена Работник 4 Отмена Работник 6 Отмена Работник 8 Работник 0 Отменен Работник 1 Возвращена: 1 Работник 2 Отменен Работник 3 Возвращено: 3 Работник 4 Отменен 3 Возвращена: 3 Работник Отменен 7 Вернулся: 7 Работник 8 Отменен Работник 9 Вернулся: 9
(Обратите внимание, что это workers
, нет workres
).