Force re-use of thread by CompletableFuture

允我心安 提交于 2019-12-24 00:49:47

问题


I am making critical use of:

 CompletableFuture
  .delayedExecutor(1, TimeUnit.MILLISECONDS).execute(() -> {});

From what I have read online, it's common for this to use a new thread for every call. I am wondering if there is a way to re-use a thread instead of creating new threads?

Update:

I wasn't clear - I want to use CompletableFuture, but I want CompletableFuture to reuse a certain thread, instead of managing its own threads.

I see this question: CompletableFuture reuse thread from pool

but it recommends using an environment variable - I am wondering if there is a way to do this programmatically.


回答1:


From what I have read online, it's common for this to use a new thread for every call.

(1) It's the case only if the machine doesn't support parallelism or you made it to not support it by setting the system property java.util.concurrent.ForkJoinPool.common.parallelism to 0 or 1.

8 processors

(2) If the machine does support parallelism, ForkJoinPool.commonPool() is used and the parallelism level is set, I guess, to the number of available processors (which can be determined by Runtime#availableProcessors).

In a scenario with 8 processors, 7-8 threads will probably be created to serve the common ForkJoinPool.

I want to use CompletableFuture, but I want CompletableFuture to reuse a certain thread, instead of managing its own threads.

A DelayedExecutor just submits tasks to the underlying Executor, which is either a ThreadPerTaskExecutor (1) or a ForkJoinPool (2).

Fortunately, you can manually specify an Executor which will be employed by the DelayedExecutor to delegate tasks to.

Executor delayedExecutor = 
     CompletableFuture.delayedExecutor(1, TimeUnit.MILLISECONDS, executor);

It gets us back to your previous question, where I pointed out that an Executor can be defined with a ThreadFactory.

Executor executor = Executors.newCachedThreadPool(YourThreadClass::new);



回答2:


Executor new Thread is created for every set of tasks

An Executor is normally used instead of explicitly creating threads. For example, rather than invoking new Thread(new(RunnableTask())).start() for each of a set of tasks, you might use: for each of a set of tasks

Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());

So if you want to reuse the threads, create a thread pool by using ExecutorService or ThreadPoolExecutor, so one of the threads from the pool will execute the runnable tasks.

If all the threads are busy, tasks will be queued up to a certain limit and after that will get rejected through a RejectedExecutionException.

Example

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 Use CompletableFuture.runAsync and pass runnable, Executor

public static CompletableFuture runAsync(Supplier supplier, Executor executor)

Returns a new CompletableFuture that is asynchronously completed by a task running in the given executor after it runs the given action.



来源:https://stackoverflow.com/questions/54564805/force-re-use-of-thread-by-completablefuture

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!