2012-08-01 11 views
5

Tengo un solo objeto de subproceso Objeto ExecutorService. En algún momento en el futuro, las tareas se agregan para hacerse usando el método submit(). Según tengo entendido, enviar presentará el Runnable enviado al final de la lista de tareas pendientes. Sin embargo, tengo una situación en la que, en función de un booleano, es posible que desee enviar el ejecutable al frente de las tareas que se ejecutarán. No quiero que esto afecte la tarea actual, solo que la siguiente tarea será la que acabo de darle. Un ejemplo de método se reproduce a continuación. ¿Cómo hago esto?Java interject Objetos ejecutables en ExecutorService

Gracias

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

Respuesta

4

Mi preferencia sería utilizar un LinkedBlockingDeque. Admite directamente las inserciones/eliminaciones de posición - putFirst(e)/takeFirst() y putLast(e)/takeLast() - que es su requisito principal - no tiene que implementar un Comparator para sus elementos. También esto está limitado, lo que significa que brinda seguridad contra OutOfMemoryError.

editar En respuesta a la última pregunta:

En primer lugar, tiene la ExecutorService como

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

En segundo lugar, la pregunta importante es: ¿cuál es la workQueue?

El workQueue es una envoltura delgada sobre cualquier BlockingQueue aplicación, que delega todas sus métodos a una instancia LinkedBlockingDeque que contiene, excepto por el método offer(), que se llama en él por el ThreadPoolExecutor y que debe ser anulado, al igual esto:

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

Por supuesto, cuando se reemplaza cualquier método - que necesita para cuidado de preservar la seguridad y su hilo en general contract.Definitely esto requiere una cuidadosa reflexión y pruebas rigurosas.

+0

Esto es exactamente lo que necesito, gracias – Jon

+0

Mejor que mi solución :) –

+0

Así que solo iba a implementar esto y tengo una pregunta más, ¿cómo exactamente puedo agregar trabajos a la cola? ¿Tengo que anular ThreadPoolExecutor ya que no puedo agregar objetos Runnable a LinkedBlockingDeque? – Jon

1

Creo que su mejor enfoque para esto sería a instantiate a ThreadPoolExecutor con un PriorityBlockingQueue. Específicamente, use un constructor de PriorityBlockingQueue que tome un Comparator. Su Comparator será lo que use para implementar su 'prioridad'.

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

Gracias por la respuesta, ¿podría darnos un ejemplo de un PriorityComparator? – Jon

+0

Eche un vistazo a la interfaz 'Comparador' (ahora vinculada en la respuesta). Es probable que necesite implementar su propio "Comparador", pero debería ser relativamente sencillo. –

+0

Mi problema es que no entiendo cómo obtener mi booleano en el Comparador. Para compilar, necesito hacer una clase con la siguiente firma de firma privada. RunnableComparator implementa Comparador . El Comparador necesita comparar los tipos Runnable y no puede comparar las clases que implementan Runnable y solo puede haber 1 Comparator que necesita ser instanciado antes de que el ExecutorService pueda ser instanciado, por lo que el booleano doNow no puede pasarse a él. – Jon

Cuestiones relacionadas