Рассмотрим приложение Swing с JList или JTable, когда при изменении выбора запускается SwingWorker, который загружает связанные данные из базы данных и обновляет пользовательский интерфейс. Это отлично работает, а пользовательский интерфейс отзывчивый.
Но если пользователь быстро меняет выбранную строку (удерживая клавишу вверх / вниз), я хочу быть уверен, что последняя выбранная строка - это та, которая загружена последней, а также я не хочу запрашивать БД в напрасно. Так что мне нужен однопоточный Executor с LIFO-очередью размером = 1. Таким образом, отправка ему задачи удаляет все предыдущие отправленные задачи и заставляет ее выполнять не более 1 задачи за раз, а не более 1 задачи ожидает ее выполнения.
Я не смог найти ничего подобного в java.util.concurrent, поэтому я написал своего собственного исполнителя. Я был прав в этом или я что-то упустил из параллельного пакета? Является ли решение приемлемым или есть лучшие способы достижения того, чего я хочу?
public class SingleLIFOExecutor implements Executor
{
private final ThreadPoolExecutor executor;
private Runnable lastCommand;
public SingleLIFOExecutor()
{
executor = new ThreadPoolExecutor(0, 1, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1));
}
@Override
public void execute(Runnable command)
{
executor.remove(lastCommand);
lastCommand = command;
executor.execute(command);
}
}
А вот пример, показывающий, как его можно использовать:
final Executor executor = new SingleLIFOExecutor();
JList jList = createMyList();
jList.addListSelectionListener(new ListSelectionListener()
{
@Override
public void valueChanged(ListSelectionEvent e)
{
if (!e.getValueIsAdjusting())
{
executor.execute(new MyWorker());
}
}
});