Intentaré explicar este problema con un código completamente funcional. Pero antes de sumergirme en el código, me gustaría explicar sobre PriorityBlockingQueue
PriorityBlockingQueue: PriorityBlockingQueue es una implementación de BlockingQueue. Acepta las tareas junto con su prioridad y envía la tarea con la más alta prioridad para su ejecución primero. Si dos tareas tienen la misma prioridad, debemos proporcionar alguna lógica personalizada para decidir qué tarea va primero.
Ahora entremos en el código inmediatamente.
Clase de controlador: Esta clase crea un ejecutor que acepta tareas y luego las envía para su ejecución. Aquí creamos dos tareas, una con prioridad baja y otra con prioridad ALTA. Aquí le decimos al ejecutor que ejecute un MAX de 1 subprocesos y use PriorityBlockingQueue.
public static void main(String[] args) {
/*
Minimum number of threads that must be running : 0
Maximium number of threads that can be created : 1
If a thread is idle, then the minimum time to keep it alive : 1000
Which queue to use : PriorityBlockingQueue
*/
PriorityBlockingQueue queue = new PriorityBlockingQueue();
ThreadPoolExecutor executor = new ThreadPoolExecutor(0,1,
1000, TimeUnit.MILLISECONDS,queue);
MyTask task = new MyTask(Priority.LOW,"Low");
executor.execute(new MyFutureTask(task));
task = new MyTask(Priority.HIGH,"High");
executor.execute(new MyFutureTask(task));
task = new MyTask(Priority.MEDIUM,"Medium");
executor.execute(new MyFutureTask(task));
}
clase MyTask: MyTask implementa Ejecutable y acepta prioridad como un argumento en el constructor. Cuando se ejecuta esta tarea, imprime un mensaje y luego pone el hilo en modo de suspensión durante 1 segundo.
public class MyTask implements Runnable {
public int getPriority() {
return priority.getValue();
}
private Priority priority;
public String getName() {
return name;
}
private String name;
public MyTask(Priority priority,String name){
this.priority = priority;
this.name = name;
}
@Override
public void run() {
System.out.println("The following Runnable is getting executed "+getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
clase MyFutureTask: Ya que estamos usando PriorityBlocingQueue para la celebración de nuestras tareas, las tareas debe ser envuelto en el interior FutureTask y nuestra aplicación de FutureTask debe implementar la interfaz Comparable. La interfaz Comparable compara la prioridad de 2 tareas diferentes y envía la tarea con la mayor prioridad para la ejecución.
public class MyFutureTask extends FutureTask<MyFutureTask>
implements Comparable<MyFutureTask> {
private MyTask task = null;
public MyFutureTask(MyTask task){
super(task,null);
this.task = task;
}
@Override
public int compareTo(MyFutureTask another) {
return task.getPriority() - another.task.getPriority();
}
}
Clase de prioridad: explica por sí misma clase de prioridad.
public enum Priority {
HIGHEST(0),
HIGH(1),
MEDIUM(2),
LOW(3),
LOWEST(4);
int value;
Priority(int val) {
this.value = val;
}
public int getValue(){
return value;
}
}
Ahora cuando nos encontramos este ejemplo, obtenemos el siguiente resultado
The following Runnable is getting executed High
The following Runnable is getting executed Medium
The following Runnable is getting executed Low
A pesar de que hemos presentado la baja prioridad en primer lugar, pero tarea de alta prioridad más tarde, pero ya que estamos utilizando un PriorityBlockingQueue, cualquier la tarea con una prioridad más alta se ejecutará primero.
Interesante pregunta. Esto parece un poco un descuido en la API, en mi opinión. –
Si tuviera que adivinar por qué no forma parte de la API, diría que probablemente sea porque la cuestión del hambre es complicada. Tendrían que proporcionar un nuevo conjunto de primitivas para la equidad y la escalada; cosas como must-execute-by y may-be-indefinitely-deferred (tenga en cuenta que estoy sacando estos nombres de mi trasero). Me gustaría que lo hubieran hecho, pero no los culpo :) –
Sí, eso tiene sentido. Parece que sería algo bueno tener, sin embargo, pero cuando crees que necesitas esencialmente escribir un algoritmo de programación de CPU en Java, probablemente estés haciendo algo mal. –