FifoPriorityThreadPoolExecutor.java revision 89cd88e9c1ed197f390e186799b14b2f63b66670
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 {@link DefaultThreadFactory}.
22     * @param poolSize The number of threads.
23     */
24    public FifoPriorityThreadPoolExecutor(int poolSize) {
25        this(poolSize, poolSize, 0, TimeUnit.MILLISECONDS, new DefaultThreadFactory());
26    }
27
28    public FifoPriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAlive, TimeUnit timeUnit,
29            ThreadFactory threadFactory) {
30        super(corePoolSize, maximumPoolSize, keepAlive, timeUnit, new PriorityBlockingQueue<Runnable>(), threadFactory);
31    }
32
33    @Override
34    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
35        return new FifoPriorityLoadTask<T>(runnable, value, ordering.getAndIncrement());
36    }
37
38    public static class DefaultThreadFactory implements ThreadFactory {
39        int threadNum = 0;
40        @Override
41        public Thread newThread(Runnable runnable) {
42            final Thread result = new Thread(runnable, "image-manager-resize-" + threadNum) {
43                @Override
44                public void run() {
45                    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
46                    super.run();
47                }
48            };
49            threadNum++;
50            return result;
51        }
52    }
53
54    private static class FifoPriorityLoadTask<T> extends FutureTask<T> implements Comparable<FifoPriorityLoadTask> {
55        private final int priority;
56        private final int order;
57
58        public FifoPriorityLoadTask(Runnable runnable, T result, int order) {
59            super(runnable, result);
60            if (!(runnable instanceof Prioritized)) {
61                throw new IllegalArgumentException("FifoPriorityThreadPoolExecutor must be given Runnables that " +
62                        "implement Prioritized");
63            }
64            priority = ((Prioritized) runnable).getPriority();
65            this.order = order;
66        }
67
68        @Override
69        public int compareTo(FifoPriorityLoadTask loadTask) {
70            int result = priority - loadTask.priority;
71            if (result == 0 && loadTask != this) {
72                result = order - loadTask.order;
73            }
74            return result;
75        }
76    }
77}
78