【发布时间】:2017-12-12 01:55:54
【问题描述】:
我遇到了一个问题,似乎线程在 WAITING 状态下变得不可中断。任务线程本身(您将在下面的线程堆栈中看到)正在等待调用 FuturePromise.get()(一个 Jetty 类)。
任务线程正在 ExecutorService 的上下文中执行。下面是 ExecutorService 调用的样子(简化)。
ExecutorService es = Executors.newFixedThreadPool(8, new CustomizableThreadFactory("Test-Thread-"));
es.submit(taskToRun);
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);
es.shutdownNow();
String result = taskToRun.get();
我看到的是主线程卡在taskToRun.get() 等待任务完成/被中断,而运行任务的线程处于这种状态:
"Test-Thread-1"
#135245 prio=5 os_prio=0 tid=0x00007f972c0c2000 nid=0x6838 waiting on condition [0x00007f96ca165000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000005d00d1118> (a java.util.concurrent.CountDownLatch$Sync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)
at org.eclipse.jetty.util.FuturePromise.get(FuturePromise.java:118)
... + app code
我期望发生的是 Test-Thread-1 将被中断,这将引发 InterruptedException,而 taskToRun.get() 调用也会引发 InterruptedException。
很遗憾,我无法通过单元测试重现此问题,但我会在获得更多信息后更新。
【问题讨论】:
-
你期待
ExecutorService.shutdownNow()会导致线程中断吗? (即使 javadoc 说它可能不会) -
中断发生时,无法证明作业在
get()方法内。你的工作中可能有任何你没有表现出来的东西,包括捕捉InterruptedException或在进入get()之前轮询/清除中断状态…… -
我是迈克的同事。我们期望
awaitTermination使执行器服务超时并中断其线程。shutdownNow基本上只是一个清理步骤,假设 executorService 已经完成工作或超时。 -
> 可以是你工作中的任何东西,你没有显示,包括在进入 get() 之前捕获 InterruptedException 或轮询/清除中断状态 对,所以我们没有看到任何东西在我们工作的任何其他地方捕获了一个 InterruptedException。我想我们很困惑
executorService是如何处理这些超时的,以及如果我们在关闭之后很久才访问Future.get时会抛出 InterruptedException。理论上,InterruptedException 是否会在内部存储,然后在最终调用 Future.get 时重新抛出? -
@Bradley,
awaitTermination()实际上并没有进行中断,shutdownNow()确实,并且正在使用的实现(ThreadPoolExecutor)似乎正在使用Thread.interrupt()来中断线程。
标签: multithreading java-8 jetty executorservice futuretask