如何创建LIFO执行器?

我想创建一个线程池,它将执行最近提交的任务。 关于如何实现这一点的任何建议?

谢谢

您可能只需要实现自己的BlockingQueue包装器,它将offer / poll映射到堆栈。 然后使用它作为传递给ThreadPoolExecutorBlockingQueue实现。 我的建议是包装一个现有的Deque实现,比如ArrayDeque

  • 这是不同步的,因此您需要使用同步器包装每个BlockingQueue方法(如果不是更奇特的东西)。
  • 您还需要为阻塞操作引入wait / notify条件。
  • 最后,您需要将一组BlockingQueue极性(“put”或“take”侧)映射到出队的同一端(将其视为堆栈)。

请注意,在更快的并发堆栈上有一些工作(参见Herlihy关于多处理器编程艺术的书),但我不认为JDK中有任何实现,我不确定Herlihy的实现是否提供阻塞风格。

Deque上的实现

我检查了Android文档,这表明Deque适合你,所以这是一个实现。 在堆栈周围做包装也是一个相当容易的步骤,但Deque是首选。

 import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.concurrent.BlockingDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; public final class BlockingLifoQueue implements BlockingQueue { // we add and remove only from the end of the queue private final BlockingDeque deque; public BlockingLifoQueue() { deque = new LinkedBlockingDeque(); } public boolean add(T e) { deque.addLast(e); return true; } public boolean contains(Object o) { return deque.contains(o); } public int drainTo(Collection c) { return deque.drainTo(c); } public int drainTo(Collection c, int maxElements) { return deque.drainTo(c,maxElements); } public boolean offer(T e) { return deque.offerLast(e); } public boolean offer(T e, long timeout, TimeUnit unit) throws InterruptedException { return deque.offerLast(e,timeout,unit); } public T poll(long timeout, TimeUnit unit) throws InterruptedException { return deque.pollLast(timeout, unit); } public void put(T e) throws InterruptedException { deque.putLast(e); } public int remainingCapacity() { return deque.size(); } public boolean remove(Object o) { return deque.remove(o); } public T take() throws InterruptedException { return deque.takeLast(); } public T element() { if (deque.isEmpty()) { throw new NoSuchElementException("empty stack"); } return deque.pollLast(); } public T peek() { return deque.peekLast(); } public T poll() { return deque.pollLast(); } // deque.peekLast(); } -- fixed typo. public T remove() { if (deque.isEmpty()) { throw new NoSuchElementException("empty stack"); } return deque.pollLast(); } public boolean addAll(Collection c) { for (T e : c) { deque.add(e); } return true; } public void clear() { deque.clear();} public boolean containsAll(Collection c) { return deque.containsAll(c); } public boolean isEmpty() { return deque.isEmpty(); } public Iterator iterator() { return deque.descendingIterator(); } public boolean removeAll(Collection c) { return deque.removeAll(c); } public boolean retainAll(Collection c) { return deque.retainAll(c); } public int size() { return deque.size(); } public Object[] toArray() { return deque.toArray(); } public  T[] toArray(T[] a) { return deque.toArray(a); } } 

与andersoj建议的类似,但是有BlockingDeque的可用性。

您可以将LinkedBlockingDeque类扩展为始终在提供和删除时弹出并首先推送。

 public class FIFOBlockingDeque extends LinkedBlockingDeque { @Override public boolean offer(T t) { return super.offerFirst(t); } @Override public T remove() { return super.removeFirst(); } } 

然后将其作为参数传递给ThreadPoolExecutor(BlockingDeque extends BlockingQueue)

编辑:要回答您的评论问题,您可以使用提供的java.util.Stack而不是inheritanceDeque。 它被认为是遗留的,如果你只局限于Java库本身,这将是最好的。

您可以使用push和pop来代替offerFirst和removeFirst。 当然,您必须实现BlockingQueue并完成该实现。

这可以通过使用PriorityQueuePriorityBlockingQueue轻松完成,其中最近排队的项目具有最高优先级。

ThreadPoolExecutor构造函数接受用于保持任务执行的BlockingQueue 。 您可能需要实现BlockingQueue的自定义版本以支持LIFO策略。

在BlockingLifoQueue的方法中,我认为LIFO的@andersoj实现中存在错误。

remove方法应该是这样的:

  public T remove() { if (deque.isEmpty()) { throw new NoSuchElementException("empty stack"); } return deque.pollFirst(); // instead of pollLast() } 

对不起,如果我错了,但对我来说没有意义……在LIFO中查看Last。