Java 使用ThreadPoolExecutor使用CompletableFuture时,在各个线程上设置超时

Java 使用ThreadPoolExecutor使用CompletableFuture时,在各个线程上设置超时,java,multithreading,completable-future,Java,Multithreading,Completable Future,我有一个使用ThreadPoolExecutor异步执行的程序。我使用Java8中的CompletableFutures来调度这些任务,然后让线程池中可用的线程执行这些任务 我的代码如下所示: public class ThreadTest { public void print(String m) { System.out.println(m); } public class One implements Callable<Integer>

我有一个使用ThreadPoolExecutor异步执行的程序。我使用Java8中的CompletableFutures来调度这些任务,然后让线程池中可用的线程执行这些任务

我的代码如下所示:

public class ThreadTest {

    public void print(String m) {
        System.out.println(m);
    }

    public class One implements Callable<Integer> {

        public Integer call() throws Exception {
            print("One...");
            Thread.sleep(6000);
            print("One!!");
            return 100;
        }
    }

    public class Two implements Callable<String> {

        public String call() throws Exception {
            print("Two...");
            Thread.sleep(1000);
            print("Two!!");
            return "Done";
        }
    }

    @Test
    public void poolRun() throws InterruptedException, ExecutionException {
        int n = 3;
        // Build a fixed number of thread pool
        ExecutorService pool = Executors.newFixedThreadPool(n);

        CompletableFuture futureOne = CompletableFuture.runAsync(() -> new One());
        // Wait until One finishes it's task.
        CompletableFuture futureTwo = CompletableFuture.runAsync(() -> new One());
        // Wait until Two finishes it's task.
        CompletableFuture futureTwo = CompletableFuture.runAsync(() -> new Two());

        CompletableFuture.allOf(new CompletableFuture[]{futureOne, futureTwo, futureThree}).get();
        pool.shutdown();
    }
}
我需要在每个线程上设置一个超时,例如设置为10分钟超时。 我研究了CompletableFuture的.getTimeUnit timeUnit方法,但我不确定这是在线程池上还是在单个线程本身上设置了超时

或者我应该改变使用executor服务在各个线程上设置超时的方式吗

谢谢

您所指的get方法仅指您等待个人未来的时间。默认情况下,即使超时,任务也将继续执行

如果要在线程超时时停止线程执行,以便该线程可以执行其他操作,则需要在捕获TimeoutException时取消该任务。例如:

    try {
        result = future.get(10, TimeUnit.MINUTES);
    } catch (TimeoutException e) {
        future.cancel(true);
    }

注意:这假设您有一个定期检查中断的任务。IO绑定的任务通常会执行此操作,但CPU绑定的任务通常需要明确检查中断的线程,以使取消生效。

CompletableFuture.get不会停止运行任务的线程。只要您指定结果,调用线程就会等待,如果超时,它将抛出异常。但是运行任务的线程将继续运行,直到任务完成。 下面是潜在的现实:Java不允许您在任何时候任意终止任务。曾经有一段时间,这是API的一部分,Thread类上有Thread.suspend/resume/stop方法。 这些被弃用,因为无法知道挂起或停止的线程是否持有可能阻止其他线程执行的锁。因此,在任意时间和地点停止线程本质上是不安全的。您的程序最终会出现死锁

请看这里:

相同的参数适用于并发包中的任何池、执行器和其他类。不能任意停止线程或任务

您必须将停止和完成的逻辑放入任务本身,或者只需等待任务完成。在本例中,一个运行一秒钟,另一个运行6秒钟。您可以使用互斥量和信号量之类的东西,您可以使用concurrent包和concurrent.locks包中的许多东西,所有这些都有助于协调线程并传递有关线程位置的信息

但是,您在任何地方都找不到允许您在任何时间点杀死任意线程的方法,除了上面列出的那些以前不推荐使用的方法,以及鼓励您远离的那些方法

Future.cancel将停止任务的启动,并尝试中断正在运行的任务,但它所做的一切都是通过使线程抛出InterruptedException来停止线程,该异常当前在可中断方法调用(如thread.sleep、Object.wait或Condition.wait)上被阻止。如果您的任务正在执行其他操作,它将不会停止,直到它完成或调用可中断的方法调用

这将对上面的代码起作用,因为您正在调用Thread.sleep。但一旦你的任务完成了,它就会像我描述的那样