我使用ExecutorService为我的应用编写了一个懒惰的图像下载器。它使我可以很好地控制在什么时候等时间并行运行多少个下载。
现在,我唯一的问题是,如果我提交任务,它最终将排在队列的尾部(FIFO)。
有人知道如何将其更改为LIFO吗?
最佳答案
您将需要指定ExecutorService使用的队列类型。
通常,您可能通过Executors中的静态方法检索ExecutorService。相反,您将需要直接实例化一个实例,然后传递您想要提供LIFO的Queue类型。
EG,要创建LIFO线程池执行程序,可以使用以下构造函数。
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
并传入LIFO队列作为最终参数。
我知道的Java集合中没有LIFO队列(如果出错,请更正),但是您可以轻松地创建一个扩展LinkedBlockingQueue并覆盖适当方法的匿名内部类。
例如,(未测试)
ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 16, 1, TimeUnit.MINUTES, new LinkedBlockingQueue() {
@Override
public void put(Object obj) {
// override to put objects at the front of the list
super.addFirst(obj);
}
});
更新以回应评论。
我们可以使用包装优先级队列的阻塞队列。我们必须包装一下,因为执行程序需要可运行对象,但我们也需要时间戳记。
// the class that will wrap the runnables
static class Pair {
long timestamp;
Runnable runnable;
Pair(Runnable r) {
this.timestamp = System.currentTimeMillis();
this.runnable = r;
}
}
ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 16, 1, TimeUnit.MINUTES, new BlockingQueue<Runnable>() {
private Comparator comparator = new Comparator<Pair>() {
@Override
public int compare(Pair arg0, Pair arg1) {
Long t1 = arg0.timestamp;
Long t2 = arg1.timestamp;
// compare in reverse to get oldest first. Could also do
// -t1.compareTo(t2);
return t2.compareTo(t1);
}
};
private PriorityBlockingQueue<Pair> backingQueue = new PriorityBlockingQueue<Pair>(11, comparator);
@Override
public boolean add(Runnable r) {
return backingQueue.add(new Pair(r));
}
@Override
public boolean offer(Runnable r) {
return backingQueue.offer(new Pair(r));
}
@Override
public boolean offer(Runnable r, long timeout, TimeUnit unit) {
return backingQueue.offer(new Pair(r), timeout, unit);
}
// implement / delegate rest of methods to the backing queue
});
关于android - 使用LIFO订购的执行器服务,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6107609/