我正在使用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
我正在尝试对客户端代码进行基准测试.所以我决定编写一个多线程程序来对我的客户端代码进行基准测试.我正在尝试测量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) 自定义线程池的建议大小为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(甚至更多)有什么问题?