Я хотел бы создать пул потоков, который будет выполнять самую последнюю отправленную задачу. Любые советы о том, как это сделать?
Спасибо
Я хотел бы создать пул потоков, который будет выполнять самую последнюю отправленную задачу. Любые советы о том, как это сделать?
Спасибо
Возможно, вы могли бы просто реализовать свою собственную BlockingQueue
оболочку, которая отображает предложение/опрос в стек. Затем используйте это как реализацию BlockingQueue
, которую вы передаете в ThreadPoolExecutor
. Мое предложение было бы обернуть одну из существующих реализаций Deque
, таких как ArrayDeque
.
BlockingQueue
синхронизатором (если не более экзотическим).wait
/notify
для операций блокировки.BlockingQueue
(либо "положить", либо "взять" ) на тот же конец детекции, что и другой (чтобы рассматривать его как стек),Обратите внимание, что есть некоторая работа (см. книгу Херлихи по искусству многопроцессорного программирования) на более быстрых параллельных стеках, но я не думаю, что в JDK есть какие-либо реализации, и я не уверен, что реализации Herlihy предлагают блокирующие ароматы.
Я проверил документацию 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<T> implements BlockingQueue<T>
{
// we add and remove only from the end of the queue
private final BlockingDeque<T> deque;
public BlockingLifoQueue()
{ deque = new LinkedBlockingDeque<T>(); }
public boolean add(T e) {
deque.addLast(e);
return true;
}
public boolean contains(Object o)
{ return deque.contains(o); }
public int drainTo(Collection<? super T> c)
{ return deque.drainTo(c); }
public int drainTo(Collection<? super T> 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<? extends T> 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<T> 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> T[] toArray(T[] a)
{ return deque.toArray(a); }
}
Похоже на то, что предложил andersoj, однако есть доступность BlockingDeque.
Вы можете расширить класс LinkedBlockingDeque, чтобы всегда всплывать и нажимать сначала, когда предлагаете и удаляете.
public class FIFOBlockingDeque<T> extends LinkedBlockingDeque<T> {
@Override
public boolean offer(T t) {
return super.offerFirst(t);
}
@Override
public T remove() {
return super.removeFirst();
}
}
Затем передайте это как параметр ThreadPoolExecutor (BlockingDeque расширяет BlockingQueue)
Изменить: Чтобы ответить на ваш вопрос с вопросом, вы можете вместо наследования с Deque, вы можете использовать поставляемый java.util.Stack. Это считается наследием, если вы ограничены самой библиотекой Java, это было бы лучше всего.
Вместо предложения first и removeFirst вы можете использовать push и pop. Конечно, вам придется реализовать BlockingQueue и завершить эту реализацию.
Это легко осуществить с помощью PriorityQueue
или PriorityBlockingQueue
, в котором самые последние поставленные в очередь элементы получают наивысший приоритет.
ThreadPoolExecutor
принимают BlockingQueue
, который используется для выполнения задач. Вероятно, вам понадобится реализовать настроенную версию BlockingQueue
для поддержки политики LIFO.
Я думаю, что в реализации @andersoj LIFO есть ошибка в методе BlockingLifoQueue.
Метод remove должен выглядеть следующим образом:
public T remove()
{
if (deque.isEmpty()) {
throw new NoSuchElementException("empty stack");
}
return deque.pollFirst(); // instead of pollLast()
}
Извините, если я ошибаюсь, но для меня это не имеет смысла... опросить Last в LIFO.