FifoPriorityThreadPoolExecutor.java revision b5419dc08eb0a0f82821d774435720e5a31bc936
1package com.bumptech.glide.load.engine.executor;
2
3import java.util.concurrent.FutureTask;
4import java.util.concurrent.PriorityBlockingQueue;
5import java.util.concurrent.RunnableFuture;
6import java.util.concurrent.ThreadFactory;
7import java.util.concurrent.ThreadPoolExecutor;
8import java.util.concurrent.TimeUnit;
9import 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 */
17public 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 FifoPriorityLoadTask<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    private static class FifoPriorityLoadTask<T> extends FutureTask<T> implements Comparable<FifoPriorityLoadTask> {
61        private final int priority;
62        private final int order;
63
64        public FifoPriorityLoadTask(Runnable runnable, T result, int order) {
65            super(runnable, result);
66            if (!(runnable instanceof Prioritized)) {
67                throw new IllegalArgumentException("FifoPriorityThreadPoolExecutor must be given Runnables that "
68                        + "implement Prioritized");
69            }
70            priority = ((Prioritized) runnable).getPriority();
71            this.order = order;
72        }
73
74        @Override
75        public int compareTo(FifoPriorityLoadTask loadTask) {
76            int result = priority - loadTask.priority;
77            if (result == 0 && loadTask != this) {
78                result = order - loadTask.order;
79            }
80            return result;
81        }
82    }
83}
84