在本文中,我们将详细介绍newFixedThreadPool与newSingleThreadExecutor的性能问题的各个方面,并为您提供关于newfixedthreadpool参数都有哪些的相关解
在本文中,我们将详细介绍newFixedThreadPool与newSingleThreadExecutor的性能问题的各个方面,并为您提供关于newfixedthreadpool参数都有哪些的相关解答,同时,我们也将为您带来关于CachedThreadPool/FixedThreadPool/SingleThreadExecu、com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor的实例源码、Executors.newCachedThreadPool 源码解析、Executors.newCachedThreadPool() 与 Executors.newFixedThreadPool()的有用知识。
本文目录一览:- newFixedThreadPool与newSingleThreadExecutor的性能问题(newfixedthreadpool参数都有哪些)
- CachedThreadPool/FixedThreadPool/SingleThreadExecu
- com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor的实例源码
- Executors.newCachedThreadPool 源码解析
- Executors.newCachedThreadPool() 与 Executors.newFixedThreadPool()
newFixedThreadPool与newSingleThreadExecutor的性能问题(newfixedthreadpool参数都有哪些)
我正在尝试对我们的客户代码进行基准测试。因此,我决定编写一个多线程程序来对我的客户端代码进行基准测试。我正在尝试测量time (95Percentile)
下面的方法需要多少?
attributes = deClient.getDEAttributes(columnsList);
因此,下面是我编写的用于对上述方法进行基准测试的多线程代码。在两种情况下,我看到了很多变化-
1)首先,使用20 threads
和来处理多线程代码running for 15 minutes
。我得到95%的37ms
。我正在使用-
ExecutorService service = Executors.newFixedThreadPool(20);
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 startTime = System.currentTimeMillis(); long endTime = startTime + (15 * 60 * 1000);//Running for 15 minutes for (int i = 0; i < threads; i++) { service.submit(new ServiceTask(endTime, serviceList)); } // wait for termination service.shutdown(); service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); } catch (InterruptedException e) { } catch (Exception e) { }}
下面是实现Runnable接口的类-
class ServiceTask implements Runnable { private static final Logger LOG = Logger.getLogger(ServiceTask.class.getName()); private static Random random = new SecureRandom(); public static volatile AtomicInteger countSize = new AtomicInteger(); private final long endTime; private final LinkedHashMap<String, ServiceInfo> tableLists; public static ConcurrentHashMap<Long, Long> selectHistogram = new ConcurrentHashMap<Long, Long>(); public ServiceTask(long endTime, LinkedHashMap<String, ServiceInfo> tableList) { this.endTime = endTime; this.tableLists = tableList; } @Override public void run() { try { while (System.currentTimeMillis() <= endTime) { double randomNumber = random.nextDouble() * 100.0; ServiceInfo service = selectRandomService(randomNumber); final String id = generateRandomId(random); final List<String> columnsList = getColumns(service.getColumns()); List<DEAttribute<?>> attributes = null; DEKey bk = new DEKey(service.getKeys(), id); List<DEKey> list = new ArrayList<DEKey>(); list.add(bk); Client deClient = new Client(list); final long start = System.nanoTime(); attributes = deClient.getDEAttributes(columnsList); final long end = System.nanoTime() - start; final long key = end / 1000000L; boolean done = false; while(!done) { Long oldValue = selectHistogram.putIfAbsent(key, 1L); if(oldValue != null) { done = selectHistogram.replace(key, oldValue, oldValue + 1); } else { done = true; } } countSize.getAndAdd(attributes.size()); handleDEAttribute(attributes); if (BEServiceLnP.sleepTime > 0L) { Thread.sleep(BEServiceLnP.sleepTime); } } } catch (Exception e) { } }}
更新:-
这是我的处理器规格-我正在Linux机器上运行程序,其中2个处理器定义为:
vendor_id : GenuineIntelcpu family : 6model : 45model name : Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHzstepping : 7cpu MHz : 2599.999cache size : 20480 KBfpu : yesfpu_exception : yescpuid level : 13wp : yesflags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology tsc_reliable nonstop_tsc aperfmperf pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm arat pln ptsbogomips : 5199.99clflush size : 64cache_alignment : 64address sizes : 40 bits physical, 48 bits virtualpower management:
答案1
小编典典谁能告诉我
newSingleThreadExecutor
vs 如此高性能问题的原因是什么newFixedThreadPool(20)
?
如果并行运行的任务(如果是20个)比处理器(我怀疑您有20个以上的处理器)要多得多,那么是的,每个单独的任务将需要更长的时间才能完成。对于计算机而言,一次执行一个任务比在同时运行的多个线程之间切换要容易得多。即使将池中的线程数限制为拥有的CPU数,每个任务的运行速度可能也会变慢,尽管会略有降低。
但是,如果比较不同大小的线程池的 吞吐量
(完成多个任务所需的时间),则应该看到20个线程的吞吐量应该更高。如果您用20个线程执行1000个任务,则总体而言,完成任务要比仅使用1个线程快得多。每个任务可能需要更长的时间,但它们将并行执行。给定线程开销等,它可能不会快20倍,但是可能快15倍。
您不必担心单个任务的速度,而应该通过调整池中的线程数来尝试最大化任务吞吐量。使用多少线程在很大程度上取决于IO数量,每个任务使用的CPU周期,锁,同步块,在OS上运行的其他应用程序以及其他因素。
就池中的线程数而言,人们通常会使用1-2倍的CPU作为启动内存的最佳位置,以最大程度地提高吞吐量。更多的IO请求或线程阻塞操作将添加更多的线程。更多的CPU绑定将减少线程数,使其更接近可用的CPU数。如果您的应用程序正在与服务器上其他更重要的应用程序竞争OS周期,则可能需要更少的线程。
CachedThreadPool/FixedThreadPool/SingleThreadExecu
1. CachedThreadPool会创建尽可能为每一个提交的runnable创建一个线程,如果有空闲线程则优先利用空闲线程。
2.FixedThreadPool创建确定数量的线程。
3.创建一个线程。
线程池如何回收旧线程?
com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor的实例源码
@Override public void applyOptions(Context context,GlideBuilder builder) { //builder.setMemoryCache(new LruResourceCache(64 * 1024 * 1024)); //builder.setBitmapPool(new LruBitmapPool(32 * 1024 * 1024)); builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); builder.setdiskCache(new InternalCachediskCacheFactory(context,2147483647)); builder.setResizeService(new FifoPriorityThreadPoolExecutor(2)); }
@Override public void applyOptions(Context context,2147483647)); builder.setResizeService(new FifoPriorityThreadPoolExecutor(2)); }
@Override public void applyOptions(Context context,GlideBuilder builder) { //if (VERSION.SDK_INT == VERSION_CODES.KITKAT) builder.setResizeService(new FifoPriorityThreadPoolExecutor(4)); }
@Override public void applyOptions(Context context,GlideBuilder builder) { // debug: make sure there's enough threads so delay transformations don't block the others builder.setdiskCacheService(new FifoPriorityThreadPoolExecutor(20)); builder.setResizeService(new FifoPriorityThreadPoolExecutor(20)); }
Executors.newCachedThreadPool 源码解析
Executors 还有个常用静态方法 newCachedThreadPool (),来构造线程池 今天我们其源码实现,探一探究竟
//底层还是调用ThreadPoolExecutor,不过参数有变化
//corePoolSize 竟然为0,maximumPoolSize为默认的最大值
//当任务队列满时,就会判断maximumPoolSize大小
//keepAliveTime 空闲线程的最大等待时间,,60s后立马销毁线程了
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
####SynchronousQueue 注意这个队列
A {@linkplain BlockingQueue blocking queue} in which each insert
* operation must wait for a corresponding remove operation by another
* thread, and vice versa. A synchronous queue does not have any
* internal capacity, not even a capacity of one.
- SynchronousQueue,实际上它不是一个真正的队列,因为它不会为队列中元素维护存储空间。与其他队列不同的是,它维护一组线程,这些线程在等待着把元素加入或移出队列。
- 在使用 SynchronousQueue 作为工作队列的前提下,客户端代码向线程池提交任务时,而线程池中又没有空闲的线程能够从 SynchronousQueue 队列实例中取一个任务,那么相应的 offer 方法调用就会失败(即任务没有被存入工作队列)。此时,ThreadPoolExecutor 会新建一个新的工作者线程用于对这个入队列失败的任务进行处理(假设此时线程池的大小还未达到其最大线程池大小 maximumPoolSize)。
newFixedThreadPool 和 newCachedThreadPool 最大差别就是 队列,线程回收的时间
###newFixedThreadPool 应用场景
Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to <tt>execute</tt> will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources.
newFixedThreadPool 线程池的数量是不确定的,可以无限大。 它比较适合处理执行时间比较小的任务
Executors.newCachedThreadPool() 与 Executors.newFixedThreadPool()
newCachedThreadPool()
相对newFixedThreadPool()
我什么时候应该使用其中一种?在资源利用方面哪种策略更好?
答案1
小编典典我认为文档很好地解释了这两个函数的区别和用法:
newFixedThreadPool
创建一个线程池,该线程池重用在共享无界队列上运行的固定数量的线程。在任何时候,最多 nThreads
个线程将是活动的处理任务。如果在所有线程都处于活动状态时提交了其他任务,它们将在队列中等待,直到有线程可用。如果任何线程在关闭之前的执行过程中由于失败而终止,如果需要执行后续任务,新的线程将取代它。池中的线程将一直存在,直到显式关闭。
newCachedThreadPool
创建一个线程池,根据需要创建新线程,但在可用时将重用以前构造的线程。这些池通常会提高执行许多短期异步任务的程序的性能。如果可用,对执行的调用将重用以前构造的线程。如果没有可用的现有线程,将创建一个新线程并将其添加到池中。六十秒内未使用的线程将被终止并从缓存中删除。因此,保持空闲足够长时间的池不会消耗任何资源。请注意,可以使用
ThreadPoolExecutor 构造函数创建具有相似属性但细节不同(例如超时参数)的池。
在资源方面,newFixedThreadPool
它将保持所有线程运行,直到它们被显式终止。在newCachedThreadPool
60
秒内未使用的线程将被终止并从缓存中删除。
鉴于此,资源消耗将在很大程度上取决于具体情况。例如,如果您有大量长时间运行的任务,我建议使用FixedThreadPool
.
至于CachedThreadPool
,文档说“这些池通常会提高执行许多短期异步任务的程序的性能”。
今天的关于newFixedThreadPool与newSingleThreadExecutor的性能问题和newfixedthreadpool参数都有哪些的分享已经结束,谢谢您的关注,如果想了解更多关于CachedThreadPool/FixedThreadPool/SingleThreadExecu、com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor的实例源码、Executors.newCachedThreadPool 源码解析、Executors.newCachedThreadPool() 与 Executors.newFixedThreadPool()的相关知识,请在本站进行查询。
本文标签: