Это будет невозможно без использования резьбы. Что-то должно установитьabort()
перед тем, как бегущая нить остановится. Взгляните на этот пример:
class Solver implements Runnable {
private List<Case> cases;
public Solver(List<Case> cases) {
this.cases = cases;
}
private void compute(Case c) {
try {
// Do some computation here
} finally {
// Sound the horns! Abandon ship!
}
}
public void solve(List<Object> cases) {
for (Case c : cases) {
try {
compute(c); // method that take too long to finish
} catch (InterruptedException e) {
// Hmm, maybe I should take the hint...
break;
}
}
}
public void run() {
solve(cases);
}
public static void main(String args[]) {
List<Case> cases = new ArrayList<Case>();
// Populate cases
Thread t = new Thread(new Solver(cases));
t.run();
do {
// Wait 30 seconds
t.join(30 * 1000);
// Not done yet? Lets drop a hint..
if(t.isAlive()) {
t.interrupt();
}
} while (t.isAlive());
}
}
Очень просто, он запускает решение в потоке. Основной поток ожидает до 30 секунд, затем прерывает метод solve
. Метод solve
ловит прерывание и изящно выходит из вычислений. В отличие от вашего решения с использованием boolean abort
, это запускает InterruptedException
из любого места вашего кода thead (и вы должны иметь дело с этим исключением), позволяя вам остановить выполнение в любое время.
Если вы хотите большего контроля, вы можете добавить try.. catch
внутри compute
, так что вы можете иметь предложение finally
, чтобы закрыть все открытые файлы или еще что-то еще. Возможно, еще лучше, чтобы вычислить try.. finally
, чтобы справиться с закрытием вещей «хорошим» способом и try.. catch (InterruptedException)
в методе solve
для обработки того, что происходит в случае прерывания (короче говоря, логика очистки и логика прерывания не должны быть в том же методе).
[shutdown()] (https://docs.oracle.com/javase/8/docs /api/java/util/concurrent/ExecutorService.html#shutdown--) делает не что иное, как предотвращение запуска новых задач и оставление текущих потоков, выполняемых как они есть, и [shutdownNow()] (https://docs.oracle.com /javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow--) просто вызывает прерывание при выполнении задач. Никто не предлагал ничего убить. – Neil
Вы правы, но лучше использовать shutdownNow(), затем разобраться с ним в своем собственном коде, по существу изобретая колесо, написав собственный ExecutionService –
True. Я, вероятно, использовал бы ExecutionService, если бы я хотел запускать каждый случай параллельно или что-то минимально сложнее, чем пример выше. Конечно, неплохая идея, чтобы предпочесть ее по теме. Однако логика прерывания в коде потока не изменилась. – Neil