2010-11-13 6 views
3

Envisager une application Swing avec un JList ou JTable, lorsque la sélection change, un SwingWorker est démarré et charge les données connexes à partir de la base de données et met à jour l'interface utilisateur. Cela fonctionne bien et l'interface utilisateur est réactive."Single LIFO Executor"/SwingWorker

Mais si l'utilisateur change rapidement la ligne sélectionnée (en maintenant la touche enfoncée), je veux être sûr que la dernière ligne sélectionnée est celle qui est chargée en dernier, et aussi je ne veux pas interroger la BD en vain. Donc ce que je veux, c'est un Executor à un seul thread avec une file d'attente LIFO de taille = 1. Ainsi, l'envoi d'une tâche supprime toutes les tâches soumises précédemment et la fait exécuter au plus une tâche à la fois et avoir au plus une tâche en attente d'exécution.

Je n'ai rien trouvé de pareil dans java.util.concurrent alors j'ai écrit mon propre Executor. Avais-je raison de le faire ou ai-je oublié quelque chose dans le paquet concurrent? La solution est-elle acceptable ou existe-t-il de meilleurs moyens de réaliser ce que je veux?

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); 
    } 
} 

Et voici un exemple montrant comment il pourrait être utilisé:

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()); 
     } 
    } 
}); 

Répondre

0

Ce fut la solution que je mis en œuvre, fonctionne très bien pour le problème que j'ai essayé de résoudre :)

/** 
* 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); 
    } 
} 
0

BlockingDeque Je crois est ce que vous voulez. Il supporte les piles.

Ce que j'ai dans mon code:

private transient final ExecutorService threadPool= 
    new ThreadPoolExecutor(3, 10,10, 
          TimeUnit.MILLISECONDS, 
          new LinkedBlockingDeque<Runnable>()); 
1

LinkedBlockingDeque semble toujours utiliser avec Queues ThreadPoolExecutor.

Ainsi, au lieu que j'utiliser un emballage et utilisé avec le 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); 
    } 
}