ExecutorService 使用 invokeAll 和超时异常后可调用线程上的超时未终止
Posted
技术标签:
【中文标题】ExecutorService 使用 invokeAll 和超时异常后可调用线程上的超时未终止【英文标题】:ExecutorService using invokeAll and timeout on callables thread not got terminated after timeout exception 【发布时间】:2021-08-27 08:22:58 【问题描述】:我尝试在线程上设置超时,并期望执行程序抛出异常并阻止线程形式运行它终止它,但这不是超时工作发现的情况 但线程完成执行。 如果它通过超时,我如何终止线程? 这是我的测试代码:
class ArithmeticBB implements ArithmeticManagerCallable.ArithmeticAction
@Override
public String arithmetic(String n)
try
Thread.sleep(5000);
catch (InterruptedException e)
e.printStackTrace();
String ss = n+" 2" + " ,Thread ID:" +Thread.currentThread().getId();
return ss;
public class ArithmeticManagerCallable
ExecutorService executor = null;
private List<String> integerList = null;
private List<String> myResult= Collections.synchronizedList(new ArrayList<>());
private int threadTimeOutInSec = 180;
public ArithmeticManagerCallable(List<String> dataFromUser, int poolSize, int threadTimeOutInSec)
this.integerList = dataFromUser;
executor = Executors.newFixedThreadPool(poolSize);
this.threadTimeOutInSec = threadTimeOutInSec;
private void exec(ArithmeticAction arithmeticAction)
List<String> tempList = new ArrayList<>();
for(Iterator<String> iterator = integerList.listIterator(); iterator.hasNext();)
tempList.add(arithmeticAction.arithmetic(iterator.next()));
resultArray.addAll(tempList);
public List<String> invokerActions(List<ArithmeticAction> actions) throws
InterruptedException
Set<Callable<String>> callables = new HashSet<>();
for (final ArithmeticAction ac : actions)
callables.add(new Callable<String>()
public String call() throws Exception
exec(ac);
return "done";
);
List<Future<String>> futures = executor.invokeAll(callables, this.threadTimeOutInSec, TimeUnit.SECONDS);
executor.shutdown();
while (!executor.isTerminated())
return myResult;
public interface ArithmeticAction
String arithmetic(String n);
public static void main(String[] args)
List<ArithmeticManagerCallable.ArithmeticAction> actions = new ArrayList();
actions.add(new ArithmeticBB());
List<String> intData = new ArrayList<>();
intData.add("1");
ArithmeticManagerCallable arithmeticManagerCallable = new ArithmeticManagerCallable(intData,20,4);
try
List<String> result = arithmeticManagerCallable.invokerActions(actions);
System.out.println("***********************************************");
for(String i : result)
System.out.println(i);
catch (InterruptedException e)
e.printStackTrace();
【问题讨论】:
【参考方案1】:您的Thread
在超过超时后没有完成它的执行。
请看这个例子作为参考:
ExecutorService executorService = Executors.newFixedThreadPool(20);
List<Callable<String>> callableList = new ArrayList<>();
for (int i = 0; i < 10; i++)
final int identifier = i;
callableList.add(()->
try
Thread.sleep(1000 * identifier);
catch (InterruptedException e)
System.out.println("I'm " + identifier + " and my sleep was interrupted.");
return identifier + " Hello World";
);
try
List<Future<String>> futureList = executorService.invokeAll(callableList, 5, TimeUnit.SECONDS);
for (Future<String> result : futureList)
System.out.println(result.get());
catch (InterruptedException | ExecutionException e)
System.out.println("Something went wrong while executing. This may help: " + e.getMessage());
catch (CancellationException e)
System.out.println("Not all Futures could be received.");
finally
executorService.shutdown();
【讨论】:
谢谢,我也知道 executorService 永远不会抛出 TimeoutException ,我怎么知道它是超时的?来自线程的中断异常。睡眠不是来自 executorService 它自己 @user63898invokeAll
不会抛出 TimeoutException
。如果您想知道未来是否在完成执行之前超时,那么您必须通过它的第二个 get-Method 直接询问 Future。 -> V get(long timeout, TimeUnit unit)
我喜欢从 TimeoutException 类型中捕获异常,以便我有指标。我注意到这是我做的: executor.submit(new CallableinvokeAll
允许您一次提交多个Callable
s。如果您现在通过invokeAll
执行它们或逐个提交它们,则取决于您作为开发人员。
谢谢我喜欢调用不阻塞的东西以上是关于ExecutorService 使用 invokeAll 和超时异常后可调用线程上的超时未终止的主要内容,如果未能解决你的问题,请参考以下文章
ExecutorService.invokeAny()和ExecutorService.invokeAll()的使用剖析