我正在关键地使用:
CompletableFuture
.delayedExecutor(1, TimeUnit.MILLISECONDS).execute(() -> {});
从我在网上读到的内容来看,每次调用都使用一个新线程是很常见的。我想知道是否有办法重用线程而不是创建新线程?
更新:
我不清楚 - 我想使用CompletableFuture
,但我希望CompletableFuture
重用某个线程,而不是管理它自己的线程。
我看到这个问题: 池中的可压缩未来重用线程
但它建议使用环境变量 - 我想知道是否有办法以编程方式执行此操作。
从我在网上读到的内容来看,每次调用都使用一个新线程是很常见的。
(1) 仅当计算机不支持并行性或通过将系统属性java.util.concurrent.ForkJoinPool.common.parallelism
设置为0
或1
使其不支持并行性时,才会出现这种情况。
8 个处理器
(2)如果机器确实支持并行性,则使用ForkJoinPool.commonPool()
,并且并行度级别设置为可用处理器的数量(可以通过Runtime#availableProcessors
确定)。
在具有 8 个处理器的场景中,可能会创建 7-8 个线程来为公共ForkJoinPool
提供服务。
我想使用
CompletableFuture
,但我希望CompletableFuture
重用某个线程,而不是管理它自己的线程。
DelayedExecutor
只是将任务提交到底层Executor
,即ThreadPerTaskExecutor
(1)或ForkJoinPool
(2)。
幸运的是,您可以手动指定DelayedExecutor
将用于委派任务的Executor
。
Executor delayedExecutor =
CompletableFuture.delayedExecutor(1, TimeUnit.MILLISECONDS, executor);
这让我们回到了你之前的问题,我指出Executor
可以用ThreadFactory
来定义。
Executor executor = Executors.newCachedThreadPool(YourThreadClass::new);
为每组任务创建执行器 新线程
通常使用执行器而不是显式创建线程。例如,与其为一组任务中的每一个调用新的 Thread(new(RunnableTask())).start(),不如使用: 对于一组任务中的每一个
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
因此,如果要重用线程,请使用ExecutorService
或ThreadPoolExecutor
创建线程池,以便池中的一个线程将执行可运行的任务。
如果所有线程都繁忙,任务将排队到一定限制,之后将通过RejectedExecutionException
被拒绝。
例
public class NewMain {
private static final ExecutorService ex = Executors.newFixedThreadPool(3);
public static void main(String[] args) {
Runnable r = () -> System.out.println(Thread.currentThread().getName());
ex.execute(r);
CompletableFuture<Void> c = CompletableFuture.runAsync(r, ex);
}
}
Jdk-8使用CompletableFuture.runAsync
和传递可运行,执行器
公共静态可压缩未来运行异步(供应商供应商, 遗嘱执行人)
返回一个新的 CompletableFuture,该任务在运行给定操作后由在给定执行器中运行的任务异步完成。