阻塞在未来的线程会发生什么情况,相应的任务已被丢弃?
What happens to a thread blocking on a future which corresponding task has been discarded?
我正在使用 ExecutorService
在线程池上执行一些计算:
@Override
public double predict(IModelInputData<EXTRACTER> modelInputData) throws PredictionFailureException {
try {
return threadPool.submit(() -> regressor.predict(modelInputData)).get();
} catch (InterruptedException|ExecutionException e) {
throw new PredictionFailureException("Error during prediction", e);
}
}
已使用有界阻塞队列和自定义策略创建执行程序服务 threadPool
:
private static class DiscardOldestWithWarningPolicy extends ThreadPoolExecutor.DiscardOldestPolicy {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
super.rejectedExecution(r, e);
LOG.warn("Discarded the oldest prediction task (too many tasks in the queue)");
}
}
我进行了测试以确保确实记录了此警告,确实如此,但是我非常不确定当相应任务被丢弃时阻塞在 threadPool.submit(...).get()
上的线程会发生什么情况。在我看来,它们一直处于阻塞状态,但这没有多大意义。我希望看到的行为是抛出异常以中断线程,但我还没有看到任何异常。
我是不是漏掉了什么?
是的,看起来内置的 DiscardOldestPolicy 只是将最旧的丢弃在地板上。问题是 ThreadPoolExecutor 持有一个 Runnable,并且无法知道如何处理它。您可以实现自己的处理程序,它对任务做一些有用的事情(对 Runnable 的类型做出假设)。
类似于:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
Runnable old = e.getQueue().poll();
if(old instanceof Future<?>) {
((Future<?>)old).cancel(true);
}
e.execute(r);
}
}
我正在使用 ExecutorService
在线程池上执行一些计算:
@Override
public double predict(IModelInputData<EXTRACTER> modelInputData) throws PredictionFailureException {
try {
return threadPool.submit(() -> regressor.predict(modelInputData)).get();
} catch (InterruptedException|ExecutionException e) {
throw new PredictionFailureException("Error during prediction", e);
}
}
已使用有界阻塞队列和自定义策略创建执行程序服务 threadPool
:
private static class DiscardOldestWithWarningPolicy extends ThreadPoolExecutor.DiscardOldestPolicy {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
super.rejectedExecution(r, e);
LOG.warn("Discarded the oldest prediction task (too many tasks in the queue)");
}
}
我进行了测试以确保确实记录了此警告,确实如此,但是我非常不确定当相应任务被丢弃时阻塞在 threadPool.submit(...).get()
上的线程会发生什么情况。在我看来,它们一直处于阻塞状态,但这没有多大意义。我希望看到的行为是抛出异常以中断线程,但我还没有看到任何异常。
我是不是漏掉了什么?
是的,看起来内置的 DiscardOldestPolicy 只是将最旧的丢弃在地板上。问题是 ThreadPoolExecutor 持有一个 Runnable,并且无法知道如何处理它。您可以实现自己的处理程序,它对任务做一些有用的事情(对 Runnable 的类型做出假设)。
类似于:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
Runnable old = e.getQueue().poll();
if(old instanceof Future<?>) {
((Future<?>)old).cancel(true);
}
e.execute(r);
}
}