相关疑难解决方法(0)

默认的ForkJoinPool执行器需要很长时间

我正在使用CompletableFuture来异步执行从列表源生成的流.

所以我正在测试重载方法,即CompletableFuture的"supplyAsync",其中一个方法只接受单个供应商参数,另一个方法接受供应商参数和执行者参数.以下是两者的文档:

supplyAsync(供应商供应商)

返回由ForkJoinPool.commonPool()中运行的任务异步完成的新CompletableFuture,其中包含通过调用给定供应商获得的值.

第二

supplyAsync(供应商供应商,执行执行人)

返回由给定执行程序中运行的任务异步完成的新CompletableFuture,其中包含通过调用给定供应商获得的值.

这是我的测试类:

public class TestCompleteableAndParallelStream {

    public static void main(String[] args) {
        List<MyTask> tasks = IntStream.range(0, 10)
                .mapToObj(i -> new MyTask(1))
                .collect(Collectors.toList());

        useCompletableFuture(tasks);

        useCompletableFutureWithExecutor(tasks);

    }

    public static void useCompletableFutureWithExecutor(List<MyTask> tasks) {
          long start = System.nanoTime();
          ExecutorService executor = Executors.newFixedThreadPool(Math.min(tasks.size(), 10));
          List<CompletableFuture<Integer>> futures =
              tasks.stream()
                   .map(t -> CompletableFuture.supplyAsync(() -> t.calculate(), executor))
                   .collect(Collectors.toList());

          List<Integer> result =
              futures.stream()
                     .map(CompletableFuture::join)
                     .collect(Collectors.toList());
          long duration = (System.nanoTime() - start) / 1_000_000;
          System.out.printf("Processed %d tasks in %d millis\n", tasks.size(), duration); …
Run Code Online (Sandbox Code Playgroud)

executorservice java-8 threadpoolexecutor forkjoinpool completable-future

6
推荐指数
2
解决办法
6338
查看次数

newFixedThreadPool与newSingleThreadExecutor的性能问题

我正在尝试对客户端代码进行基准测试.所以我决定编写一个多线程程序来对我的客户端代码进行基准测试.我正在尝试测量time (95 Percentile)以下方法将采取多少 -

attributes = deClient.getDEAttributes(columnsList);

下面是我编写的用于对上述方法进行基准测试的多线程代码.我在两个场景中看到很多变化 -

1)首先,使用20 threads和使用多线程代码running for 15 minutes.我获得95%的百分比37ms.我正在使用 -

ExecutorService service = Executors.newFixedThreadPool(20);
Run Code Online (Sandbox Code Playgroud)

2)但如果我正在运行同样的程序以15 minutes使用 -

ExecutorService service = Executors.newSingleThreadExecutor();

代替

ExecutorService service = Executors.newFixedThreadPool(20);

7ms当我运行我的代码时,我得到95百分位,这比上面的数字小newFixedThreadPool(20).

任何人都能告诉我这样的高性能问题可能是什么原因 -

newSingleThreadExecutor vs newFixedThreadPool(20)

通过这两种方式,我正在运行我的程序15 minutes.

以下是我的代码 -

public static void main(String[] args) {

    try {

        // create thread pool with given size
        //ExecutorService service = Executors.newFixedThreadPool(20);
        ExecutorService service = Executors.newSingleThreadExecutor();

        long …
Run Code Online (Sandbox Code Playgroud)

java concurrency performance multithreading threadpool

4
推荐指数
1
解决办法
4799
查看次数

线程池大小应远大于核心数+ 1

自定义线程池的建议大小为number_of_cores + 1(请参见此处此处).因此,假设在具有2个内核的系统上有一个Spring应用程序,配置就像这样

<task:executor id="taskExecutor" 
pool-size="#{T(java.lang.Runtime).getRuntime().availableProcessors() + 1}" />
<task:annotation-driven executor="taskExecutor" />
Run Code Online (Sandbox Code Playgroud)

在这种情况下,将在多个请求之间共享一个ExecutorService.因此,如果10个请求到达服务器,则只能在ExecutorService中同时执行其中3个请求.这可能会产生瓶颈,并且结果会随着请求数量的增加而变得更糟(请记住:默认情况下,tomcat最多可以处理200个并发请求= 200个线程).该应用程序将执行得更好,没有任何池.

通常,一个核心可以同时处理多个线程.例如,我创建了一个服务,它调用两次https://httpbin.org/delay/2.每次调用都需要2秒才能执行.因此,如果没有使用线程池,则服务平均响应4.5秒(使用20个同时请求进行测试).如果使用线程池,则响应因池大小和硬件而异.我在具有不同池大小的4核心机器上运行测试.以下是最小,最大和平均响应时间(以毫秒为单位)的测试结果

最小,最大和平均响应时间(以毫秒为单位)

从结果可以得出结论,最佳平均时间是最大池大小.池中5(4个核心+ 1)线程的平均时间比没有池的结果更糟糕.因此,在我看来,如果请求不占用大量CPU时间,那么将线程池限制为Web应用程序中的核心数+ 1是没有意义的.

对于非CPU要求的Web服务,是否有人发现在2或4核心机器上将池大小设置为20(甚至更多)有什么问题?

java multithreading tomcat threadpool

0
推荐指数
1
解决办法
1138
查看次数