Ich werde versuchen, dieses Problem anhand eines voll funktionsfähigen Codes zu erklären. Aber bevor ich in den Code eintauche, möchte ich etwas über PriorityBlockingQueue erklären
PriorityBlockingQueue : PriorityBlockingQueue ist eine Implementierung von BlockingQueue. Sie nimmt die Aufgaben mit ihrer Priorität entgegen und gibt die Aufgabe mit der höchsten Priorität zuerst zur Ausführung frei. Wenn zwei Aufgaben die gleiche Priorität haben, müssen wir eine benutzerdefinierte Logik bereitstellen, um zu entscheiden, welche Aufgabe zuerst ausgeführt wird.
Kommen wir gleich zum Code.
Klasse der Fahrer : Diese Klasse erstellt einen Executor, der Aufgaben annimmt und sie später zur Ausführung übergibt. Hier erstellen wir zwei Aufgaben, eine mit NIEDRIGER Priorität und die andere mit HOHER Priorität. Hier weisen wir den Executor an, MAX von 1 Threads auszuführen und die PriorityBlockingQueue zu verwenden.
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));
}
MyTask-Klasse : MyTask implementiert Runnable und akzeptiert die Priorität als Argument im Konstruktor. Wenn diese Aufgabe ausgeführt wird, gibt sie eine Nachricht aus und versetzt den Thread dann für 1 Sekunde in den Ruhezustand.
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();
}
}
}
MyFutureTask-Klasse : Da wir PriorityBlocingQueue zur Aufnahme unserer Tasks verwenden, müssen unsere Tasks in FutureTask verpackt werden und unsere Implementierung von FutureTask muss die Schnittstelle Comparable implementieren. Die Comparable-Schnittstelle vergleicht die Priorität von 2 verschiedenen Tasks und übergibt den Task mit der höchsten Priorität zur Ausführung.
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();
}
}
Prioritätsklasse : Selbsterklärend Prioritätsklasse.
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;
}
}
Wenn wir nun dieses Beispiel ausführen, erhalten wir folgende Ausgabe
The following Runnable is getting executed High
The following Runnable is getting executed Medium
The following Runnable is getting executed Low
Auch wenn wir die Aufgabe mit NIEDRIGER Priorität zuerst, die mit HOHER Priorität aber später eingereicht haben, wird jede Aufgabe mit höherer Priorität zuerst ausgeführt, da wir eine PriorityBlockingQueue verwenden.