Java &引用;“单一后进先出执行人”摇摆工人

Java &引用;“单一后进先出执行人”摇摆工人,java,swing,concurrency,swingworker,executor,Java,Swing,Concurrency,Swingworker,Executor,考虑使用JList或JTable的Swing应用程序,当选择更改时,SwingWorker将启动并从数据库加载相关数据并更新UI。这可以很好地工作,用户界面响应迅速 但是,如果用户正在快速更改所选行(按住键向上/向下),我希望确保最后选择的行是最后加载的行,而且我不想徒劳地查询数据库。所以我想要的是一个单线程执行器,其后进先出队列的大小为1。因此,向其提交任务将删除以前提交的任何任务,并使其一次最多执行一个任务,最多有一个任务等待执行 我在java.util.concurrent中找不到类似的东

考虑使用JList或JTable的Swing应用程序,当选择更改时,SwingWorker将启动并从数据库加载相关数据并更新UI。这可以很好地工作,用户界面响应迅速

但是,如果用户正在快速更改所选行(按住键向上/向下),我希望确保最后选择的行是最后加载的行,而且我不想徒劳地查询数据库。所以我想要的是一个单线程执行器,其后进先出队列的大小为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);
    }
}

我相信封锁德克是你想要的。它支持堆栈

我的代码中包含的内容:

private transient final ExecutorService threadPool= 
     new ThreadPoolExecutor(3, 10,10, 
                            TimeUnit.MILLISECONDS, 
                            new LinkedBlockingDeque<Runnable>());
private临时最终执行器服务线程池=
新线程池执行器(3、10、10、,
TimeUnit.ms,
新LinkedBlockingDeque());

LinkedBlockingDeque似乎仍然使用ThreadPoolExecutor的队列

因此,我使用了一个包装器,并将其与ThreadPoolExecutor一起使用:

package util;

import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 * LIFO BlockingQueue to be used with the ExecutorService.
 * @author Daniel
 * @param <T>
 */
public class LinkedBlockingStack<T> implements BlockingQueue<T>{
    private final LinkedBlockingDeque<T> stack = new LinkedBlockingDeque<T>();

    @Override
    public T remove() {
        return stack.remove();
    }

    @Override
    public T poll() {
        return stack.poll();
    }

    @Override
    public T element() {
        return stack.element();
    }

    @Override
    public T peek() {
        return stack.peek();
    }

    @Override
    public int size() {
        return stack.size();
    }

    @Override
    public boolean isEmpty() {
        return stack.isEmpty();
    }

    @Override
    public Iterator<T> iterator() {
        return stack.iterator();
    }

    @Override
    public Object[] toArray() {
        return stack.toArray();
    }

    @Override
    public <S> S[] toArray(final S[] a) {
        return stack.toArray(a);
    }

    @Override
    public boolean containsAll(final Collection<?> c) {
        return stack.containsAll(c);
    }

    @Override
    public boolean addAll(final Collection<? extends T> c) {
        return stack.addAll(c);
    }

    @Override
    public boolean removeAll(final Collection<?> c) {
        return stack.removeAll(c);
    }

    @Override
    public boolean retainAll(final Collection<?> c) {
        return stack.removeAll(c);
    }

    @Override
    public void clear() {
        stack.clear();
    }

    @Override
    public boolean add(final T e) {
        return stack.offerFirst(e); //Used offerFirst instead of add.
    }

    @Override
    public boolean offer(final T e) {
        return stack.offerFirst(e); //Used offerFirst instead of offer.
    }

    @Override
    public void put(final T e) throws InterruptedException {
        stack.put(e);
    }

    @Override
    public boolean offer(final T e, final long timeout, final TimeUnit unit)
    throws InterruptedException {
        return stack.offerLast(e, timeout, unit);
    }

    @Override
    public T take() throws InterruptedException {
        return stack.take();
    }

    @Override
    public T poll(final long timeout, final TimeUnit unit)
    throws InterruptedException {
        return stack.poll();
    }

    @Override
    public int remainingCapacity() {
        return stack.remainingCapacity();
    }

    @Override
    public boolean remove(final Object o) {
        return stack.remove(o);
    }

    @Override
    public boolean contains(final Object o) {
        return stack.contains(o);
    }

    @Override
    public int drainTo(final Collection<? super T> c) {
        return stack.drainTo(c);
    }

    @Override
    public int drainTo(final Collection<? super T> c, final int maxElements) {
        return stack.drainTo(c, maxElements);
    }
}
package-util;
导入java.util.Collection;
导入java.util.Iterator;
导入java.util.concurrent.BlockingQueue;
导入java.util.concurrent.LinkedBlockingDeque;
导入java.util.concurrent.TimeUnit;
/**
*要与Executor服务一起使用的后进先出阻塞队列。
*@作者丹尼尔
*@param
*/
公共类LinkedBlockingStack实现阻塞队列{
私有最终LinkedBlockingDeque堆栈=新LinkedBlockingDeque();
@凌驾
公共部门不能删除(){
返回stack.remove();
}
@凌驾
公众投票{
返回stack.poll();
}
@凌驾
公共T元素(){
返回stack.element();
}
@凌驾
公共T peek(){
返回stack.peek();
}
@凌驾
公共整数大小(){
返回stack.size();
}
@凌驾
公共布尔值为空(){
返回stack.isEmpty();
}
@凌驾
公共迭代器迭代器(){
返回stack.iterator();
}
@凌驾
公共对象[]toArray(){
返回stack.toArray();
}
@凌驾
公共S[]toArray(最终S[]a){
返回堆栈到阵列(a);
}
@凌驾
公共布尔容器(最终集合c){
返回堆栈。包含所有(c);
}
@凌驾
公共布尔addAll(最终集合c){
返回堆栈。移除所有(c);
}
@凌驾
公共布尔保留(最终集合c){
返回堆栈。移除所有(c);
}
@凌驾
公共空间清除(){
stack.clear();
}
@凌驾
公共布尔加法(最终T e){
return stack.offerFirst(e);//使用offerFirst代替add。
}
@凌驾
公开报价(最终报价){
return stack.offerFirst(e);//使用offerFirst代替offer。
}
@凌驾
公共无效put(最终T e)抛出InterruptedException{
堆栈。放置(e);
}
@凌驾
公共布尔报价(最终TE、最终长超时、最终时间单位)
抛出中断异常{
返回stack.offerLast(e,超时,单位);
}
@凌驾
public T take()抛出InterruptedException{
返回stack.take();
}
@凌驾
公共T轮询(最终长超时,最终时间单位)
抛出中断异常{
返回stack.poll();
}
@凌驾
公共剩余容量(){
返回堆栈。剩余容量();
}
@凌驾
公共布尔删除(最终对象o){
返回堆栈。移除(o);
}
@凌驾
公共布尔包含(最终对象o){
返回堆栈。包含(o);
}
@凌驾

public int drainTo(最终集合这是我实现的解决方案,非常适合我试图解决的问题:)

/**
*“单一后进先出执行人”。
*
*它维护一个任务队列,并且只有一个任务可以同时执行,
*向{@link#execute(Runnable)}提交新任务将放弃以前提交的所有尚未启动的任务。
*/
公共类SingleLIFOExecutor实现Executor
{
私人最终执行人;
私有Runnable命令;
公共SingleLIFOExecutor()
{
executor=新的ThreadPoolExecutor(0,1,0,毫秒,新的ArrayBlockingQueue(1));
}
/**
*@see java.util.concurrent.Executor#execute(java.lang.Runnable)
*/
@凌驾
public void execute(Runnable命令)
{
执行器。删除(lastCommand);
lastCommand=命令;
执行者。执行(命令);
}
}
package util;

import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 * LIFO BlockingQueue to be used with the ExecutorService.
 * @author Daniel
 * @param <T>
 */
public class LinkedBlockingStack<T> implements BlockingQueue<T>{
    private final LinkedBlockingDeque<T> stack = new LinkedBlockingDeque<T>();

    @Override
    public T remove() {
        return stack.remove();
    }

    @Override
    public T poll() {
        return stack.poll();
    }

    @Override
    public T element() {
        return stack.element();
    }

    @Override
    public T peek() {
        return stack.peek();
    }

    @Override
    public int size() {
        return stack.size();
    }

    @Override
    public boolean isEmpty() {
        return stack.isEmpty();
    }

    @Override
    public Iterator<T> iterator() {
        return stack.iterator();
    }

    @Override
    public Object[] toArray() {
        return stack.toArray();
    }

    @Override
    public <S> S[] toArray(final S[] a) {
        return stack.toArray(a);
    }

    @Override
    public boolean containsAll(final Collection<?> c) {
        return stack.containsAll(c);
    }

    @Override
    public boolean addAll(final Collection<? extends T> c) {
        return stack.addAll(c);
    }

    @Override
    public boolean removeAll(final Collection<?> c) {
        return stack.removeAll(c);
    }

    @Override
    public boolean retainAll(final Collection<?> c) {
        return stack.removeAll(c);
    }

    @Override
    public void clear() {
        stack.clear();
    }

    @Override
    public boolean add(final T e) {
        return stack.offerFirst(e); //Used offerFirst instead of add.
    }

    @Override
    public boolean offer(final T e) {
        return stack.offerFirst(e); //Used offerFirst instead of offer.
    }

    @Override
    public void put(final T e) throws InterruptedException {
        stack.put(e);
    }

    @Override
    public boolean offer(final T e, final long timeout, final TimeUnit unit)
    throws InterruptedException {
        return stack.offerLast(e, timeout, unit);
    }

    @Override
    public T take() throws InterruptedException {
        return stack.take();
    }

    @Override
    public T poll(final long timeout, final TimeUnit unit)
    throws InterruptedException {
        return stack.poll();
    }

    @Override
    public int remainingCapacity() {
        return stack.remainingCapacity();
    }

    @Override
    public boolean remove(final Object o) {
        return stack.remove(o);
    }

    @Override
    public boolean contains(final Object o) {
        return stack.contains(o);
    }

    @Override
    public int drainTo(final Collection<? super T> c) {
        return stack.drainTo(c);
    }

    @Override
    public int drainTo(final Collection<? super T> c, final int maxElements) {
        return stack.drainTo(c, maxElements);
    }
}
/**
 * A "Single Last-In-First-Out Executor".
 * <p>
 * It maintains a queue of <b>one</b> task and only one task may execute simultaneously,
 * submitting a new task to {@link #execute(Runnable)} will discard any previous submitted not yet started tasks.
 */
public class SingleLIFOExecutor implements Executor
{
    private final ThreadPoolExecutor executor;
    private Runnable lastCommand;

    public SingleLIFOExecutor()
    {
        executor = new ThreadPoolExecutor(0, 1, 0, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1));
    }

    /**
     * @see java.util.concurrent.Executor#execute(java.lang.Runnable)
     */
    @Override
    public void execute(Runnable command)
    {
        executor.remove(lastCommand);
        lastCommand = command;
        executor.execute(command);
    }
}