Comment mettre en œuvre PriorityBlockingQueue avec ThreadPoolExecutor et des tâches personnalisées
J'ai beaucoup cherché mais impossible de trouver une solutuion à mon problème.
J'ai ma propre classe, BaseTask
, qui utilise un ThreadPoolExecutor
pour gérer les tâches.
Si je ne veux pas d'ordre de priorité (c'est à dire à l'aide d'un LinkedBlockingQueue
) cela fonctionne bien, mais lorsque j'essaie d'utiliser un PriorityBlockingQueue
- je obtenir ClassCastException
parce que le ThreadPoolExecutor
enroule mes Tâches dans un FutureTask
objet.
C'est évidemment OK parce que le FutureTask
ne pas mettre en œuvre Comparable
, mais comment m'y prendre pour résoudre le problème de priorité?
J'ai lu que vous pourriez remplacer newTaskFor
dans ThreadPoolExecutor
, mais je n'arrive pas a trouver cette méthode à tous...?
Toutes les suggestions seront très appréciés!
Un peu de code pour vous aider:
Dans mon BaseTask
classe j'ai
private static final BlockingQueue<Runnable> sWorkQueue = new PriorityBlockingQueue<Runnable>();
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BaseThreadPoolExecutor sExecutor = new BaseThreadPoolExecutor(
1, Integer.MAX_VALUE, 10, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);
private final BaseFutureTask<Result> mFuture;
public BaseTask(int priority) {
mFuture = new BaseFutureTask<Result>(mWorker, priority);
}
public final BaseTask<Params, Progress, Result> execute(Params... params) {
/* Some unimportant code here */
sExecutor.execute(mFuture);
}
Dans BaseFutureTask
classe
@Override
public int compareTo(BaseFutureTask another) {
long diff = this.priority - another.priority;
return Long.signum(diff);
}
Dans BaseThreadPoolExecutor
classe je remplace les 3 submit
méthodes...
Le constructeur de cette classe est appelée, mais aucun des submit
méthodes
- Voir aussi stackoverflow.com/questions/807223/...
- Le fil de l'OP se réfère à l'est de stackoverflow.com/questions/11430574/...
Vous devez vous connecter pour publier un commentaire.
}
comme vous pouvez le deviner RunWithPriority est une classe abstraite qui est Praticable et a un Entier domaine prioritaire
Executor ex
n'est jamais utilisé? lolnew ComparePriority()
n'est pas en spécifiant le paramètre de type générique, donc je considère que c'est un moyen rapide et sale de la solution.Vous pouvez utiliser ces classes d'assistance:
ET
ET cette méthode d'assistance:
ET puis l'utiliser comme ceci:
Ma solution:
Je vais essayer d'expliquer ce problème avec un code fonctionnel. Mais avant de plonger dans le code, je tiens à expliquer à propos de PriorityBlockingQueue
PriorityBlockingQueue : PriorityBlockingQueue est une implémentation de BlockingQueue. Il accepte les tâches ainsi que leur priorité et soumet la tâche avec la plus haute priorité pour l'exécution de la première. Si deux tâches ont la même priorité, nous devons fournir de l'logique personnalisée pour décider de la tâche qui va en premier.
Maintenant permet d'obtenir dans le code tout de suite.
De la classe du pilote : Cette classe crée un exécuteur testamentaire qui accepte des tâches et, plus tard, les soumet pour l'exécution. Ici, nous créons deux tâches, l'une avec une FAIBLE priorité et l'autre avec une priorité ÉLEVÉE. Ici nous raconter l'exécuteur testamentaire pour exécuter un maximum de 1 fils et de l'utilisation de la PriorityBlockingQueue.
MyTask classe : MyTask implements Runnable et accepte de priorité comme un argument dans le constructeur. Lors de l'exécution de cette tâche, il imprime un message, puis met le fil de dormir pendant 1 seconde.
MyFutureTask classe : Puisque nous sommes à l'aide de PriorityBlocingQueue pour la tenue de nos tâches, nos tâches doivent être enveloppé à l'intérieur FutureTask et de mise en œuvre de notre FutureTask doit implémenter l'interface Comparable. L'interface Comparable compare la priorité de 2 tâches différentes et soumet la tâche avec la plus haute priorité pour l'exécution.
Classe de priorité : Auto explicative la classe de Priorité.
Maintenant, quand nous exécuter cet exemple, nous obtenons le résultat suivant
Même si nous avons soumis à la FAIBLE priorité première, mais la grande priorité de la tâche à plus tard, mais puisque nous sommes à l'aide d'un PriorityBlockingQueue, une tâche de priorité plus élevée sera exécuté en premier.
Il semble qu'ils l'ont laissé que de apache harmonie. Il y a un svn commit log il ya environ un an de fixation de l'absence de
newTaskFor
. Vous pouvez probablement juste de remplacer lesubmit
fonctions dans une longueThreadPoolExecutor
à créer unFutureTask
qui estComparable
. Ils ne sont pas très longues.submit
méthodes est appelée... Ajouté un peu de code pour aider à comprendreThreadPoolExecutor#execute
plus. Tout ce que vous voulez faire par le pool de threads sera nécessaire de passer par l'intermédiaire d'unesubmit
appel. Lesubmit
méthodes devez ensuite appelerexecute
pour vous.submit
méthode n'est juste que, appelez leexecute
méthode... Il crée un nouveauBaseFutureTask
, puis l'exécutePour répondre à votre question: La
newTaskFor()
méthode se trouve dansThreadPoolExecutor
's de la superclasse,AbstractExecutorService
. Vous pouvez simplement le remplacer dansThreadPoolExecutor
, cependant.