В моем приложении есть оболочка для некоторого нативного кода, который вызывается через мост JNI. Этот собственный код необходимо выполнять в отдельном потоке (параллельная обработка). Однако проблема в том, что код иногда «зависает», поэтому поток необходимо завершить «принудительно». К сожалению, я не нашел для этого «деликатного» метода: общий совет - сообщить коду в потоке, чтобы он завершился изящно, но я не могу сделать это с помощью этого собственного кода (который является кодом сторонних разработчиков).
Я использую Java Concurrent API для отправки задач:
Future<Integer> processFuture = taskExecutor.submit(callable);
try {
result = processFuture.get(this.executionTimeout, TimeUnit.SECONDS).intValue();
}
catch (TimeoutException e) {
// How to kill the thread here?
throw new ExecutionTimeoutException("Execution timed out (max " + this.executionTimeout / 60 + "min)");
}
catch (...) {
... exception handling for other cases
}
Future # cancel ()
только прервет поток, но не завершит его. Поэтому я использовал следующий трюк:
class DestroyableCallable implements Callable<Integer> {
private Thread workerThread;
@Override
public Integer call() {
workerThread = Thread.currentThread();
return Integer.valueOf(JniBridge.process(...));
}
public void stopWorkerThread() {
if (workerThread != null) {
workerThread.stop();
}
}
}
DestroyableCallable callable = new DestroyableCallable();
Future<Integer> processFuture = taskExecutor.submit(callable);
try {
result = processFuture.get(this.executionTimeout, TimeUnit.SECONDS).intValue();
}
catch (TimeoutException e) {
processFuture.cancel(true);
// Dirty:
callable.stopWorkerThread();
ThreadPoolTaskExecutor threadPoolTaskExecutor = (ThreadPoolTaskExecutor) taskExecutor;
logger.debug("poolSize: " + threadPoolTaskExecutor.getPoolSize() + ", maxPoolSize:"
+ threadPoolTaskExecutor.getMaxPoolSize() + ", activeCount:"
+ threadPoolTaskExecutor.getActiveCount());
}
throw new ...;
}
catch (...) {
... exception handling for other cases
}
Вопросы / проблемы с этим кодом:
activeCount
на исполнителе задачи не уменьшается, поэтому исполнитель задачи все еще «думает», что поток запущен workerThread! = Null
в stopWorkerThread ()
, поскольку в некоторых случаях эта переменная оказалась нулевой
.Я не могу понять, что это за случаи ... Примечания:
Bounty edit : Подход / предложение пересмотреть собственный код ясны, пожалуйста, не предлагайте его в своем ответе. Мне нужно решение / обходной путь на чистой Java.