超时后停止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 =

我的java代码中有一个异步链,我想在某个超时后停止它 所以我用一些线程创建了一个线程池,并像这样调用CompletableFuture

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)< /代码>,as
CompletableFuture
完全不支持中断。
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();
        }
    }
}