【发布时间】:2014-10-22 10:13:25
【问题描述】:
我有一个启动线程的可调用对象(该线程运行一个 ping 进程)我想允许用户取消任务:
public class PingCallable implements Callable<PingResult> {
private ProcThread processThread;
public PingCallable(String ip) {
this.processThread = new ProcThread(ip);
}
@Override
public PingResult call() throws Exception {
log.trace("Checking if the ip " + ip + " is alive");
try {
processThread.start();
try {
processThread.join();
} catch (InterruptedException e) {
log.error("The callable thread was interrupted for " + processThread.getName());
processThread.interrupt();
// Good practice to reset the interrupt flag.
Thread.currentThread().interrupt();
}
} catch (Throwable e) {
System.out.println("Throwable ");
}
return new PingResult(ip, processThread.isPingAlive());
}
}
ProcThread,看起来像:
@Override
public void run() {
try {
process = Runtime.getRuntime().exec("the long ping", null, workDirFile);
/* Get process input and error stream, not here to keep it short*/
// waitFor is InterruptedException sensitive
exitVal = process.waitFor();
} catch (InterruptedException ex) {
log.error("interrupted " + getName(), ex);
process.destroy();
/* Stop the intput and error stream handlers, not here */
// Reset the status, good practice
Thread.currentThread().interrupt();
} catch (IOException ex) {
log.error("Exception while execution", ex);
}
}
还有测试:
@Test
public void test() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(15);
List<Future<PingResult>> futures = new ArrayList<>();
for (int i= 0; i < 100; i++) {
PingCallable pingTask = new PingCallable("10.1.1.142");
futures.add(executorService.submit(pingTask));
}
Thread.sleep(10000);
executorService.shutdownNow();
// for (Future<PingResult> future : futures) {
// future.cancel(true);
// }
}
我使用 ProcessExplorer 监控 ping 进程,我看到 15,然后执行 shutdownNow,或者 future.cancel(true),只有 4-5 最多 8 个进程被中断,其余的保持活动状态,我几乎从来没有看到 15消息说“可调用线程被中断..”,并且测试直到进程结束才完成。 为什么?
【问题讨论】:
-
这可能与 JUnit 无法与线程一起正常工作有关。或者可能没有执行的线程完成了他们的工作
-
有任何理由拥有 ProcThread 吗?是否可以将其删除并将 run() 方法中的代码放入您的 PingCallable 中?这将简化问题。您已经有一个线程池,因此您不需要生成更多线程。
-
@pauli 我使用 ProcThread 的唯一原因是我们的许多应用程序都在使用它。我也试过了,没有产生另一个线程,但它仍然不起作用。
标签: java concurrency executorservice java.util.concurrent callable