glide溯源之线程池

glide溯源系列文章

一、 相关类
1. GlideExecutor

二、几个重要的线程池

1. 磁盘缓存线程池
 

//磁盘缓存线程池大小默认是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)));
  }

2. 核心处理线程池
 

//线程池大小默认为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);
  }

3. 动画线程池
 

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)));
  }

3. Runtime.getRuntime().availableProcessors()
a. 然而,更大的问题在于Runtime.getRuntime().availableProcessors()也并非都能返回你所期望的数值。比如说,在我的双核1-2-1机器上,它返回的是2,这是对的。不过在我的1-4-2机器 上,也就是一个CPU插槽,4核,每个核2个超线程,这样的话会返回8。不过我其实只有4个核,如果代码的瓶颈是在CPU这块的话,我会有7个线程在同时 竞争CPU周期,而不是更合理的4个线程。如果我的瓶颈是在内存这的话,那这个测试我可以获得7倍的性能提升。
b. 不过这还没完!Java Champions上的一个哥们发现了一种情况,他有一台16-4-2的机器 (也就是16个CPU插槽,每个CPU4个核,每核两个超线程,返回的值居然是16!从我的i7 Macbook pro上的结果来看,我觉得应该返回的是1642=128。在这台机器上运行Java 8的话,它只会将通用的FJ池的并发数设置成15。正如 Brian Goetz所指出的,“虚拟机其实不清楚什么是处理器,它只是去请求操作系统返回一个值。同样的,操作系统也不知道怎么回事,它是去问的硬件设备。硬件会告诉它一个值,通常来说是硬件线程数。操作系统相信硬件说的,而虚拟机又相信操作系统说的。”

猜你喜欢

转载自blog.csdn.net/qq_23081779/article/details/82772001