我有以下Task类,该类将http请求发送到API。如果该过程花费的时间太长,我想通过调用stop函数杀死该线程,但是它不起作用。
class Task implements Runnable{
private final AtomicReference<Thread> currentThread = new AtomicReference<Thread>();
private String bid;
private long id;
public Task(String bid, long id) {
this.bid = bid;
this.id = id;
}
@Override
public void run() {
currentThread.set(Thread.currentThread());
// send http request
String result = service.checkPaymentState(id, bid);
}
public void stop() {
System.out.println("stop!!!");
currentThread.get().interrupt();
}
}
主要方法。如果任务未在2秒内完成,则应将其取消:
Task task = new Task(bid, id);
Future future = taskScheduler.submit(task);
scheduledExecutorService.schedule(() -> {
if (!future.isDone()) {
System.out.println("Cancelled!");
future.cancel(true);
task.stop();
}
}, 2, TimeUnit.SECONDS);
答案 0 :(得分:3)
从ThreadPool获得的中断线程-不是一个好主意-您不知道线程池中断策略。有一天,您可以将线程池的实现更改为不创建新线程的线程池-当某些工作线程被中断并杀死时-最终您将耗尽线程池中的线程。
首选方式是调用future.cancel(true);
-在长时间运行的HTTP请求中您将获得InterruptedException
。
注意:不要捕获InterruptedException
并吞下-使其在线程池级别进行处理并应用中断策略。或者吞下它-通过Thread.currentThread().interrupt()
答案 1 :(得分:0)
您需要按以下方式重写代码:
提交任务后调用taskScheduler.shutdown()
。否则,您的 ExecutorService 将挂起,等待新的 Tasks ,并且不会让 JVM 正常关闭。
如果希望您的 Thread 在完成后返回值,请实施 Callable
正如@Oleksandr Papchenko所说:
请勿中断从 ThreadPool
获得的 Thread
在您的示例中-不要存储对池的 Thread 的引用,并在您的stop()
方法中中断它。您可以按照以下步骤重做run()
:
public String call() {
try {
/*
* describe logic of your service.checkPaymentState(id, bid) here
* if you have blocking methods wrap them in a try-catch block
*/
} catch (InterruptedException e) {
// Save the interrupted status
Thread.currentThread().interrupt();
return null;
}
return value;
}
删除stop()
方法,只需在future.cancel(true)
scheduledExecutorService
如果call()
中没有阻塞方法,则应制定自己的中断策略。例如,如果使用套接字进行中断,请在外部调用socket.close()
并在 SocketException catch子句内部实现中断。