Home | History | Annotate | Download | only in executor
      1 package com.bumptech.glide.load.engine.executor;
      2 
      3 import java.util.concurrent.FutureTask;
      4 import java.util.concurrent.PriorityBlockingQueue;
      5 import java.util.concurrent.RunnableFuture;
      6 import java.util.concurrent.ThreadFactory;
      7 import java.util.concurrent.ThreadPoolExecutor;
      8 import java.util.concurrent.TimeUnit;
      9 import java.util.concurrent.atomic.AtomicInteger;
     10 
     11 /**
     12  * A FIFO priority {@link ThreadPoolExecutor} that prioritizes submitted {@link Runnable}s by assuming they implement
     13  * {@link Prioritized}. {@link Prioritized} runnables that return lower values for {@link Prioritized#getPriority()}
     14  * will be executed before those that return higher values. Priorities only apply when multiple items are queued at the
     15  * same time. Runnables with the same priority will be executed in FIFO order.
     16  */
     17 public class FifoPriorityThreadPoolExecutor extends ThreadPoolExecutor {
     18     AtomicInteger ordering = new AtomicInteger();
     19 
     20     /**
     21      * Constructor to build a fixed thread pool with the given pool size using
     22      * {@link com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor.DefaultThreadFactory}.
     23      *
     24      * @param poolSize The number of threads.
     25      */
     26     public FifoPriorityThreadPoolExecutor(int poolSize) {
     27         this(poolSize, poolSize, 0, TimeUnit.MILLISECONDS, new DefaultThreadFactory());
     28     }
     29 
     30     public FifoPriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAlive, TimeUnit timeUnit,
     31             ThreadFactory threadFactory) {
     32         super(corePoolSize, maximumPoolSize, keepAlive, timeUnit, new PriorityBlockingQueue<Runnable>(), threadFactory);
     33     }
     34 
     35     @Override
     36     protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
     37         return new LoadTask<T>(runnable, value, ordering.getAndIncrement());
     38     }
     39 
     40     /**
     41      * A {@link java.util.concurrent.ThreadFactory} that builds threads with priority
     42      * {@link android.os.Process#THREAD_PRIORITY_BACKGROUND}.
     43      */
     44     public static class DefaultThreadFactory implements ThreadFactory {
     45         int threadNum = 0;
     46         @Override
     47         public Thread newThread(Runnable runnable) {
     48             final Thread result = new Thread(runnable, "fifo-pool-thread-" + threadNum) {
     49                 @Override
     50                 public void run() {
     51                     android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
     52                     super.run();
     53                 }
     54             };
     55             threadNum++;
     56             return result;
     57         }
     58     }
     59 
     60     // Visible for testing.
     61     static class LoadTask<T> extends FutureTask<T> implements Comparable<LoadTask<?>> {
     62         private final int priority;
     63         private final int order;
     64 
     65         public LoadTask(Runnable runnable, T result, int order) {
     66             super(runnable, result);
     67             if (!(runnable instanceof Prioritized)) {
     68                 throw new IllegalArgumentException("FifoPriorityThreadPoolExecutor must be given Runnables that "
     69                         + "implement Prioritized");
     70             }
     71             priority = ((Prioritized) runnable).getPriority();
     72             this.order = order;
     73         }
     74 
     75         @SuppressWarnings("unchecked")
     76         @Override
     77         public boolean equals(Object o) {
     78             if (o instanceof LoadTask) {
     79                 LoadTask<Object> other = (LoadTask<Object>) o;
     80                 return order == other.order && priority == other.priority;
     81             }
     82             return false;
     83         }
     84 
     85         @Override
     86         public int hashCode() {
     87             int result = priority;
     88             result = 31 * result + order;
     89             return result;
     90         }
     91 
     92         @Override
     93         public int compareTo(LoadTask<?> loadTask) {
     94             int result = priority - loadTask.priority;
     95             if (result == 0) {
     96                 result = order - loadTask.order;
     97             }
     98             return result;
     99         }
    100     }
    101 }
    102