Нить из Callable остается в состоянии ожидания. Как мне убить нить? - PullRequest
0 голосов
/ 13 октября 2019

Есть много подобных вопросов, но решения для меня не сработали.

У меня есть Callable, который должен работать в течение определенного времени. Во время выполнения метода Call, он должен периодически делать некоторые проверки в состоянии while, чтобы проверить, должен ли он продолжать работать. Я также хочу иметь возможность остановить вызываемый извне (вызов API).

Приведенный ниже код является упрощенной версией, но в ней есть та же проблема:

Когда вызываемое возвращаетсяпоток остается в состоянии ожидания. Как мне убить эту тему?

public class MyCallable implements Callable<Foo> {
    private AtomicBoolean stop = new AtomicBoolean(false);

    @Override
    public Foo call() {
        System.out.printf("New thread with ID=%d\n",
                Thread.currentThread().getId());
        Foo foo = new Foo();

        while (!stop.get()) {
            try {
                Thread.sleep(1000); // Sleep for some time before doing checks again
            } catch (InterruptedException e) {
            }
        }

        System.out.printf("State before returning foo: %s\n",
                Thread.currentThread().getState());
        return foo;
    }

    public void stop() {
        this.stop.set(true);
    }
}
public class Main {
    public static void main(String[] args) throws InterruptedException {
        MyCallable myCallable = new MyCallable();
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        Future<Foo> future = executorService.submit(myCallable);

        printThreads();

        System.out.println("Calling stop\n");
        myCallable.stop();

        while (!future.isDone()) {
            Thread.sleep(200);
        }

        System.out.println("After future is done: ");
        printThreads();
    }

    // Helper method
    private static void printThreads() {
        List<Thread> threads = Thread.getAllStackTraces().keySet()
                .stream()
                .filter(t -> t.getName().contains("pool"))
                .collect(Collectors.toList());

        threads.forEach(t -> System.out.printf("ID=%s STATE=%s\t\n", t.getId(), t.getState()));
        System.out.println();
    }
}

Это вывод программы

Output

1 Ответ

1 голос
/ 13 октября 2019

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

executorService.shutdown();

Обычно рабочий поток не завершается после выполнения одной задачи. Он перемещается в состояние WAITING, пока не появится новое задание. Эти вещи управляются ExecutorService. Выключение приведет к завершению потоков, за которые он отвечает.

...