我想将webservice调用并行发送到webservice。应该有最多20个并行请求等待Web服务响应。任何其他请求都应该等待它们完成。
如果单个用户向我发送请求,这通常会导致向目标服务器发送5个并行请求。 所以我可以立即为最多20/5 = 4个用户提供服务。其他人则必须等待,这很好。或者在真正高负荷下被拒绝。
问题:我应该使用哪个线程池,以及如何配置它?
private ExecutorService asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);
executor.initialize();
//return executor.getThreadPoolExecutor(); //I could as well use this. Which is better??
return Executors.newFixedThreadPool(20, executor);
}
我读了以上内容:主池可以向网络服务器发送20个并行请求(从而在parralel中立即为4个用户提供服务)。如果所有20个线程都忙,并且第5个用户进入,则请求排队。
问题:
配置正确吗?
为什么我必须另外在nthreads=20
设置Executors.newFixedThreadPool()
?设置poolSize
?
是否存在设置corePoolSize=20
的性能开销?我的意思是,然后游泳池将永远不会打瞌睡。但我可能无法将其设置得更低(例如为5),因为只有在队列耗尽时才会创建新线程。右
答案 0 :(得分:1)
我认为
executor.setMaxPoolSize(20)
可用于通过构造函数覆盖最初设置的线程数,在这种情况下似乎是多余的。同样适用于setCorePoolSize
。它只是用于动态控制。
根据池的大小,通常您可以考虑Little's Law
答案 1 :(得分:0)
调用Executors.newFixedThreadPool(20, executor);
时,您将先前设置的执行程序作为 ThreadFactory 传递,因为ThreadPoolTaskExecutor实现了ThreadFactory接口。
结果是一个ExecutorService,它以20个线程就绪,最大线程数20和一个无限制的LinkedBlockingQueue开始,等待处理的任务(你可以在这里看到它https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int,%20java.util.concurrent.ThreadFactory))。
关于你的第一个和第二个问题 - 你可以省略Executors.newFixedThreadPool()调用,如果你想使用jdk类ThreadPoolExecutor,只需返回ThreadPoolTaskExecutor或调用它的getThreadPoolExecutor()。
关于你的第三个问题 - 在启动时会有一个惩罚因为jvm必须创建并运行20个线程,但我猜这可以忽略不计。将corePoolSize设置为低于maximumPoolSize的一件事是,未使用的线程将被jvm杀死,这可以减少应用程序的内存占用。
关于在ExecutorService中创建新线程的时间 - 当队列中有任务并且未达到maximumPoolSize时,会创建ExecutorService中的线程。如果达到执行程序中的maximumPoolSize并且队列已满 - 执行程序将为提交给它的每个新任务抛出RejectedExecutionException,直到有新的空间。您可以通过实现自己的RejectedExecutionHandler来更改此行为。