shutdownNow со службой исполнителя

Я использую ExecutorService для задача подключения, как показано ниже:

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<ApplicationConnection> future = (Future<ApplicationConnection>) executor.submit(new ConnectThread(crf, connoptions));
connection = future.get(300000, TimeUnit.SECONDS);
executor.shutdownNow();

Метод call() вызывает метод .connect() (собственный API). Этот метод подключения порождает различные пулы потоков и т. д. Меня беспокоит то, что если время ожидания в будущем истечет и убьет исполнителя, закончатся ли потоки, которые, возможно, уже были созданы путем вызова метода .connect() в будущем? Я знаю, что уничтожение потока также уничтожит все дочерние потоки, но следует ли это той же логике?


person Greg    schedule 17.12.2012    source источник


Ответы (2)


Вы правы в своем предположении, если Future истечет время ожидания, некоторые висящие потоки останутся. Хуже того, shutdownNow() даже не остановит поток вашего пула (не говоря уже о проприетарных потоках API). Он просто перестает принимать новые рабочие места. Пул потоков ExecutorService завершит все потоки после завершения всех запущенных задач.

Что вы можете сделать, так это попытаться отменить будущее и прервать его. Сначала обработайте InterruptedException внутри своего будущего:

class ConnectThread implements Callbale<ApplicationConnection> {

    public ApplicationConnection call() {
        try {
            return prioprietaryApi.connect();
        } catch(InterruptedException e) {
            prioprietaryApi.cleanUp();
            throw e;
        }
    }

}

Теперь просто запустите:

future.cancel(true);

Однако ваш проприетарный API может не обрабатывать InterruptedException (он не будет повторно вызывать его из connect(), более того, у вас может не быть доступа к какому-либо методу cleanUp().

В этих обстоятельствах просто... забудьте об этом. Этот Future в конце концов завершится и уберет за собой, игнорируя тот факт, что вы его больше не ждете. Конечно, это может привести к различным проблемам с масштабируемостью.

Кстати, если единственное, чего вы хотите добиться, — это ограничить максимальное время выполнения данного метода, подумайте о TimeLimiter из гуава.

person Tomasz Nurkiewicz    schedule 17.12.2012
comment
Если я правильно вас понимаю, то, что я делаю сейчас, БУДЕТ оставлять висящие нити, но в конечном итоге Будущее завершится и уберет за собой? Включение future.cancel(true) будет полезно только в том случае, если метод connect() может обрабатывать InterruptedException? - person Greg; 17.12.2012
comment
@Greg: тот факт, что вы больше не ждете Future, не означает, что он больше не работает. И когда он закончит, он очистится, как обычно, однако никто особо не ждет результатов. - person Tomasz Nurkiewicz; 17.12.2012