glide之執行緒池
## 相關類 1. GlideExecutor
## 磁碟快取執行緒池 ``` //磁碟快取執行緒池大小預設是1 private static final int DEFAULT_DISK_CACHE_EXECUTOR_THREADS = 1;
public static GlideExecutor newDiskCacheExecutor() { return newDiskCacheExecutor( DEFAULT_DISK_CACHE_EXECUTOR_THREADS, DEFAULT_DISK_CACHE_EXECUTOR_NAME, UncaughtThrowableStrategy.DEFAULT); } public static GlideExecutor newDiskCacheExecutor( int threadCount, String name, UncaughtThrowableStrategy uncaughtThrowableStrategy) { return new GlideExecutor( new ThreadPoolExecutor( threadCount /* corePoolSize */, threadCount /* maximumPoolSize */, 0 /* keepAliveTime */, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>(), new DefaultThreadFactory(name, uncaughtThrowableStrategy, true))); } ```
## 核心處理執行緒池 ``` //執行緒池大小預設為4個 private static final int MAXIMUM_AUTOMATIC_THREAD_COUNT = 4;
MAXIMUM_AUTOMATIC_THREAD_COUNT public static GlideExecutor newSourceExecutor() { return newSourceExecutor( calculateBestThreadCount(), DEFAULT_SOURCE_EXECUTOR_NAME, UncaughtThrowableStrategy.DEFAULT); } public static GlideExecutor newSourceExecutor( int threadCount, String name, UncaughtThrowableStrategy uncaughtThrowableStrategy) { return new GlideExecutor( new ThreadPoolExecutor( threadCount /* corePoolSize */, threadCount /* maximumPoolSize */, 0 /* keepAliveTime */, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>(), new DefaultThreadFactory(name, uncaughtThrowableStrategy, false))); } //計算最合適的執行緒池數量 public static int calculateBestThreadCount() { if (bestThreadCount == 0) { //執行緒池大小最大為4個,4和cpu數量取小值 bestThreadCount = Math.min(MAXIMUM_AUTOMATIC_THREAD_COUNT, RuntimeCompat.availableProcessors()); } return bestThreadCount; } //獲取可用cpu數量 static int availableProcessors() { int cpus = Runtime.getRuntime().availableProcessors(); if (Build.VERSION.SDK_INT < 17) { //api-17以前的相容處理 cpus = Math.max(getCoreCountPre17(), cpus); } return cpus; } private static int getCoreCountPre17() { // We override the current ThreadPolicy to allow disk reads. // This shouldn't actually do disk-IO and accesses a device file. // See: https://github.com/bumptech/glide/issues/1170 File[] cpus = null; ThreadPolicy originalPolicy = StrictMode.allowThreadDiskReads(); try { File cpuInfo = new File(CPU_LOCATION); final Pattern cpuNamePattern = Pattern.compile(CPU_NAME_REGEX); cpus = cpuInfo.listFiles(new FilenameFilter() { @Override public boolean accept(File file, String s) { return cpuNamePattern.matcher(s).matches(); } }); } catch (Throwable t) { if (Log.isLoggable(TAG, Log.ERROR)) { Log.e(TAG, "Failed to calculate accurate cpu count", t); } } finally { StrictMode.setThreadPolicy(originalPolicy); } return Math.max(1, cpus != null ? cpus.length : 0); } ```
## 動畫執行緒池 ``` public static GlideExecutor newAnimationExecutor() { int bestThreadCount = calculateBestThreadCount(); // We don't want to add a ton of threads running animations in parallel with our source and // disk cache executors. Doing so adds unnecessary CPU load and can also dramatically increase // our maximum memory usage. Typically one thread is sufficient here, but for higher end devices // with more cores, two threads can provide better performance if lots of GIFs are showing at // once. //如果cpu數量大於等於4個,則此執行緒池大小預設為2個,否則否則為1個 int maximumPoolSize = bestThreadCount >= 4 ? 2 : 1;
return newAnimationExecutor(maximumPoolSize, UncaughtThrowableStrategy.DEFAULT); } public static GlideExecutor newAnimationExecutor( int threadCount, UncaughtThrowableStrategy uncaughtThrowableStrategy) { return new GlideExecutor( new ThreadPoolExecutor( 0 /* corePoolSize */, threadCount, KEEP_ALIVE_TIME_MS, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>(), new DefaultThreadFactory( ANIMATION_EXECUTOR_NAME, uncaughtThrowableStrategy, true))); } ```
## Runtime.getRuntime().availableProcessors() 1. 然而,更大的問題在於Runtime.getRuntime().availableProcessors()也並非都能返回你所期望的數值。比如說,在我的雙核1-2-1機器上,它返回的是2,這是對的。不過在我的1-4-2機器 上,也就是一個CPU插槽,4核,每個核2個超執行緒,這樣的話會返回8。不過我其實只有4個核,如果程式碼的瓶頸是在CPU這塊的話,我會有7個執行緒在同時 競爭CPU週期,而不是更合理的4個執行緒。如果我的瓶頸是在記憶體這的話,那這個測試我可以獲得7倍的效能提升。 2. 不過這還沒完!Java Champions上的一個哥們發現了一種情況,他有一臺16-4-2的機器 (也就是16個CPU插槽,每個CPU4個核,每核兩個超執行緒,返回的值居然是16!從我的i7 Macbook pro上的結果來看,我覺得應該返回的是1642=128。在這臺機器上執行Java 8的話,它只會將通用的FJ池的併發數設定成15。正如 Brian Goetz所指出的,“虛擬機器其實不清楚什麼是處理器,它只是去請求作業系統返回一個值。同樣的,作業系統也不知道怎麼回事,它是去問的硬體裝置。硬體會告訴它一個值,通常來說是硬體執行緒數。作業系統相信硬體說的,而虛擬機器又相信作業系統說的。”