2012-08-01 15 views
5

Ho un oggetto ExecutorService pool a thread singolo. A un certo momento in futuro verranno aggiunte le attività da eseguire utilizzando il metodo submit(). La mia comprensione è che l'invio invierà aggiungere il Runnable inviato alla fine dell'elenco di attività da eseguire. Tuttavia, ho una situazione in cui, in base a un booleano, potrei voler inviare il runnable alla parte anteriore delle attività da eseguire. Non voglio che ciò influisca sul compito corrente, solo che il prossimo compito sarà quello che ho appena dato. Un metodo di esempio è riprodotto di seguito. Come faccio a fare questo?Interject Java Oggetti eseguibili in ExecutorService

Grazie

private ExecutorService singleLoadPool = Executors.newSingleThreadExecutor(); 
public void submitTask(Runnable run, boolean doNow) { 
    if (doNow) 
     singleLoadPool.submitFront(run); // This is the method I'm looking for 
    else 
     singleLoadPool.submit(run); 
} 

risposta

4

mia preferenza sarebbe usare un LinkedBlockingDeque. Supporta direttamente inserimenti/rimuovi posizionali - putFirst(e)/takeFirst() e putLast(e)/takeLast() - che è il tuo requisito principale - non devi implementare uno Comparator per i tuoi elementi. Anche questo è limitato - il che significa che fornisce sicurezza contro OutOfMemoryError.

modifica In risposta all'ultima domanda:

In primo luogo, hanno l'ExecutorService come

ExecutorService executorService = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, workQueue);

In secondo luogo, la domanda importante è: qual è il workQueue?

Il workQueue è un involucro sottile su qualsiasi BlockingQueue attuazione, che delega tutti i metodi per un'istanza LinkedBlockingDeque che contiene, ad eccezione del metodo offer(), che è chiamato su di essa dalla ThreadPoolExecutor e che deve venire ignorate, come questo:

 public boolean offer(E e) { 
     if(doNow) 
     return linkedBlockingDequeInstance.offerFirst(e); 
     else 
     return linkedBlockingDequeInstance.offerLast(e); 
    } 

Naturalmente quando si modifica qualsiasi metodo - è necessario fare attenzione a preservare la sicurezza dei thread e il suo generale contract.Definitely questo richiede un'attenta riflessione e test rigorosi.

+0

Questo è esattamente ciò di cui ho bisogno, grazie – Jon

+0

Meglio della mia soluzione :) –

+0

Quindi stavo solo andando a implementare questo e ho ancora una domanda, in che modo esattamente aggiungere posti di lavoro alla coda? Devo sovrascrivere ThreadPoolExecutor poiché non posso semplicemente aggiungere oggetti Runnable a LinkedBlockingDeque? – Jon

1

penso che il tuo approccio migliore per questo sarebbe di instantiate a ThreadPoolExecutor con un PriorityBlockingQueue. In particolare, utilizzare un costruttore di PriorityBlockingQueue che accetta un Comparator. Il tuo Comparator sarà ciò che utilizzerai per implementare la tua 'priorità'.

PriorityBlockingQueue<Runnable> workQueue = new PriorityBlockingQueue<Runnable>(20, yourPriorityComparator); 
ExecutorService executorService = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, workQueue); 
+0

Grazie per la risposta, potresti fornire un esempio di prioritàComparator? – Jon

+0

Dai un'occhiata all'interfaccia 'Comparator' (ora collegata nella risposta). Probabilmente dovrai implementare il tuo 'Comparator', ma dovrebbe essere relativamente semplice. –

+0

Il mio problema è che non capisco come ottenere il mio booleano nel comparatore. Per compilare ho bisogno di creare una classe con la seguente classe privata RunnableComparator implementa il Comparatore . Il Comparatore deve confrontare i tipi Runnable e non può confrontare classi che implementano Runnable e può esserci solo 1 Comparator che deve essere istanziato prima che ExecutorService possa essere istanziato, quindi il doNow booleano non può essere passato ad esso. – Jon

Problemi correlati