超时后停止java CompletableFuture中的线程
我的java代码中有一个异步链,我想在某个超时后停止它 所以我用一些线程创建了一个线程池,并像这样调用CompletableFuture超时后停止java CompletableFuture中的线程,java,multithreading,concurrency,completable-future,Java,Multithreading,Concurrency,Completable Future,我的java代码中有一个异步链,我想在某个超时后停止它 所以我用一些线程创建了一个线程池,并像这样调用CompletableFuture ExecutorService pool = Executors.newFixedThreadPool(10); 然后我有一个循环方法,从数据库加载数据并对其执行一些任务,一旦所有CompletableFutures都完成了,它就会再次执行 CompletableFuture<MyObject> futureTask =
ExecutorService pool = Executors.newFixedThreadPool(10);
然后我有一个循环方法,从数据库加载数据并对其执行一些任务,一旦所有CompletableFutures都完成了,它就会再次执行
CompletableFuture<MyObject> futureTask =
CompletableFuture.supplyAsync(() -> candidate, pool)
.thenApply(Task1::doWork).thenApply(Task2::doWork).thenApply(Task3::doWork)
.thenApply(Task4::doWork).thenApply(Task5::doWork).orTimeout(30,TimeUnit.SECONDS)
.thenApply(Task6::doWork).orTimeout(30,TimeUnit.SECONDS)
.exceptionally(ExceptionHandlerService::handle);
可完成的未来任务=
CompletableFuture.SupplySync(()->候选,池)
。然后应用(Task1::doWork)。然后应用(Task2::doWork)。然后应用(Task3::doWork)
.thenApply(Task4::doWork)。thenApply(Task5::doWork)。orTimeout(30,时间单位。秒)
.thenApply(Task6::doWork).orTimeout(30,时间单位.秒)
.例外情况(例外HandlerService::handle);
我的问题在于任务6,它有一个非常密集的任务(它是一个网络连接任务,有时会永远挂起)
我注意到我的orTimeout在30秒后被正确触发,但运行Task6的线程仍在运行
在像这样的几个周期之后,我所有的线程都耗尽了,我的应用程序也死掉了
达到超时后,如何取消池中正在运行的线程?
(不调用pool.shutdown())
更新*
在主线程中,我做了一个简单的检查,如图所示
for (int i = TIME_OUT_SECONDS; i >= 0; i--) {
unfinishedTasks = handleFutureTasks(unfinishedTasks, totalBatchSize);
if(unfinishedTasks.isEmpty()) {
break;
}
if(i==0) {
//handle cancelation of the tasks
for(CompletableFuture<ComplianceCandidate> task: unfinishedTasks) {
**task.cancel(true);**
log.error("Reached timeout on task, is canceled: {}", task.isCancelled());
}
break;
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception ex) {
}
}
for(int i=超时秒;i>=0;i--){
unfinishedTasks=handleFutureTasks(unfinishedTasks,totalBatchSize);
if(unfinishedTasks.isEmpty()){
打破
}
如果(i==0){
//处理任务的取消
for(可完成的未来任务:未完成的任务){
**任务。取消(true)**
错误(“已达到任务超时,已取消:{}”,task.isCancelled());
}
打破
}
试一试{
时间单位。秒。睡眠(1);
}捕获(例外情况除外){
}
}
我看到的是,在几个周期之后,所有的任务都抱怨超时。。。
在前1-2个周期中,我仍然得到了预期的响应(尽管有线程处理它)
我仍然觉得线程池已经用完了我知道你没有调用pool.shutDown
,但是没有其他方法。但是,当您查看阶段时,它们将在“附加”它们的线程(添加那些然后应用)或您定义的池中的线程中运行。也许这是一个更有意义的例子
public class SO64743332 {
static ExecutorService pool = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> dbCall(), pool);
//simulateWork(4);
CompletableFuture<String> f2 = f1.thenApply(x -> {
System.out.println(Thread.currentThread().getName());
return transformationOne(x);
});
CompletableFuture<String> f3 = f2.thenApply(x -> {
System.out.println(Thread.currentThread().getName());
return transformationTwo(x);
});
f3.join();
}
private static String dbCall() {
simulateWork(2);
return "a";
}
private static String transformationOne(String input) {
return input + "b";
}
private static String transformationTwo(String input) {
return input + "b";
}
private static void simulateWork(int seconds) {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
} catch (InterruptedException e) {
System.out.println("Interrupted!");
e.printStackTrace();
}
}
}
运行此命令时,您应该注意到,transformationOne
会启动,但由于shutdownow
而中断
这样做的缺点应该很明显,每次调用execute
都会创建一个新的线程池…网络线程可能处于不间断睡眠状态,但不太可能处于不间断睡眠状态,在这种状态下不可能真正杀死它们。值得检查的是,这种情况不会发生。htop和其他类似工具可以显示线程是否处于不间断睡眠状态。即使评估在可中断操作中挂起,也表明您在作业中使用了错误的工具。只需考虑:“参数:<代码> MyTraceFuffunn>代码>此值在该实现中没有任何效果,因为中断不用于控制处理。”换句话说,不管您使用<代码>取消(true)< /> >还是<代码>取消(false)< /代码>,asCompletableFuture
完全不支持中断。
public class SO64743332 {
public static void main(String[] args) {
execute();
}
public static void execute() {
ExecutorService pool = Executors.newSingleThreadExecutor();
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> dbCall(), pool);
CompletableFuture<String> cf2 = cf1.thenApply(x -> transformationOne(x));
// give enough time for transformationOne to start, but not finish
simulateWork(2);
try {
CompletableFuture<String> cf3 = cf2.thenApply(x -> transformationTwo(x))
.orTimeout(4, TimeUnit.SECONDS);
cf3.get(10, TimeUnit.SECONDS);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
pool.shutdownNow();
}
}
private static String dbCall() {
System.out.println("Started DB call");
simulateWork(1);
System.out.println("Done with DB call");
return "a";
}
private static String transformationOne(String input) {
System.out.println("Started work");
simulateWork(10);
System.out.println("Done work");
return input + "b";
}
private static String transformationTwo(String input) {
System.out.println("Started transformation two");
return input + "b";
}
private static void simulateWork(int seconds) {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
} catch (InterruptedException e) {
System.out.println("Interrupted!");
e.printStackTrace();
}
}
}