Остановите бесконечный цикл в задаче ExecutorService

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

class Task implements Callable<String> {
    public String call() throws Exception {
        String s = "initial";
        try {
            System.out.println("Started..");
            /*for (int i=0;i<10000;i++) {
                if (i % 2 == 0) {
                    System.out.println("Even");
                }
            }*/
            boolean flag = true;
            while(flag) {

            }
            System.out.println("Finished!");
            s = "Done";
        }
        catch (RuntimeException e) {
            s = "RuntimeException";
        }
        catch (Exception e) {
            s = "Exception";
        }
        finally {

        }
        return s;
    }
}

public class ExecutorServiceTest {

    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        List<Future<String>> result = executor.invokeAll(Arrays.asList(new Task()), 5, TimeUnit.SECONDS);
        executor.shutdown();
        Iterator<Future<String>> iter = result.iterator();
        while (iter.hasNext()) {
            System.out.println("Came here");
            Future<String> fut = iter.next();
            System.out.println(fut.get());
        }
    }
}

Существует ли путь, которым я могу остановить поток, выполняющий бесконечный цикл?

6
задан erickson 1 March 2010 в 19:16
поделиться

2 ответа

Да, вы можете заменить флаг (или логически && ) на ! Thread.currentThread (). isInterrupted () .

Таким образом, когда задача отменена, цикл будет завершен.

Цикл будет выглядеть примерно так:

while(!Thread.currentThread().isInterrupted() && flag) {
  /* Do work. */
}

Использование должно быть примерно таким:

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> task = executor.submit(new Task());
String str;
try {
  str = task.get(5, TimeUnit.SECONDS);
} finally {
  task.cancel(true);
}
7
ответ дан 17 December 2019 в 00:08
поделиться

Подумайте об использовании synchronized (this) {this.wait ()} вместо sleep внутри call () , а затем при установке логического флаг извне (возможно, напрямую или с помощью метода flag () ; при прямом доступе убедитесь, что ваша переменная флага volatile ) call task.notifyAll ( ) , чтобы разбудить спящий поток (убедитесь, что ваш объект задачи является локальной переменной, а не анонимной, чтобы вы могли вызывать для него методы, и установите флаг для атрибута класса в Task ).

Это также будет более эффективным, потому что циклы тратятся напрасно - точный механизм называется «охраняемым блоком» ( http://java.sun.com/docs/books/tutorial/essential /concurrency/guardmeth.html). Когда вы просыпаетесь после ожидания, проверьте переменную флага, чтобы убедиться, что она установлена.

Редактировать: более внимательно рассмотрел исходный вопрос и создал пример, используя существующий код и принципы (есть несколько способов снять шкуру с кошки :)). Попробуйте это - цикл здесь завершается из-за состояния прерывания текущего потока, который был отменен из-за тайм-аута:

package ett;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

class Task implements Callable<String> {
    public String call() throws Exception {
        String s = "initial";
        System.out.println("Started..");
        for (int i=0;;i++) {
            if (i % 2 == 0) {
                System.out.println("Even");
            }
            Thread.yield();
            if (Thread.interrupted()) break;
        }
        System.out.println("Finished!");
        s = "Done";

        return s;
    }
}

public class ExecutorServiceTest {

    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        List<Future<String>> result = executor.invokeAll(Arrays.asList(new Task()), 1, TimeUnit.SECONDS);
        executor.shutdown();

        System.out.println("came here");

        for (Future<String> f : result) {
            try {
                System.out.println(f.get());
            } catch (CancellationException e) {
                e.printStackTrace();
            }
        }
    }
}
0
ответ дан 17 December 2019 в 00:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: