Plate.exécution et tâches en JavaFX
j'ai fait quelques recherches à ce sujet mais je suis encore très confus pour dire le moins.
est-ce que quelqu'un peut me donner un exemple concret de quand utiliser Task
et quand utiliser Platform.runLater(Runnable);
? Quelle est exactement la différence? Est-il une règle d'or pour quand utiliser l'un de ces?
corrigez-moi aussi si je me trompe, mais ces deux" objets " ne sont-ils pas une façon de créer un autre thread à l'intérieur du thread principal dans une interface graphique (utilisée pour mettre à jour l'interface graphique)?
4 réponses
utiliser Platform.runLater(...)
pour des opérations simples et rapides et Task
pour des opérations complexes et grandes .
- case à utiliser pour
Platform.runLater(...)
- case à utiliser pour
Task
: exemple de tâche dans L'ensemble App
exemple: Pourquoi ne pas utiliser Platform.runLater(...)
pour les longs calculs (tiré de la référence ci-dessous).
problème: Fil de fond qui ne compte que de 0 à 1 million et mettre à jour la barre de progression dans L'UI.
Code utilisant Platform.runLater(...)
:
final ProgressBar bar = new ProgressBar();
new Thread(new Runnable() {
@Override public void run() {
for (int i = 1; i <= 1000000; i++) {
final int counter = i;
Platform.runLater(new Runnable() {
@Override public void run() {
bar.setProgress(counter / 1000000.0);
}
});
}
}).start();
c'est un hideux morceau de code, un crime contre la nature (et la programmation en général). D'abord, vous perdrez des cellules cérébrales juste en regardant à ce double nid de Runnables. Deuxièmement, il va marais de la file d'attente d'événements avec petits Runnables - a millions d'entre eux en fait. Clairement, nous avions besoin D'une API pour faciliter l'écriture de background travailleurs qui communiquent ensuite avec L'IU.
Code utilisant la tâche:
Task task = new Task<Void>() {
@Override public Void call() {
static final int max = 1000000;
for (int i = 1; i <= max; i++) {
updateProgress(i, max);
}
return null;
}
};
ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();
il ne souffre d'aucun des défauts exposés dans le code précédent
référence: Travailleur Filetage en JavaFX 2.0
-
Platform.runLater
: si vous avez besoin de mettre à jour un composant GUI à partir d'un thread non-GUI, vous pouvez l'utiliser pour mettre votre mise à jour dans une file d'attente et il sera manipulé par le thread GUI dès que possible. -
Task
implémente l'interfaceWorker
qui est utilisée lorsque vous avez besoin d'exécuter une tâche longue en dehors du thread GUI (pour éviter de geler votre application) mais que vous avez encore besoin d'interagir avec l'interface GUI à un certain stade.
If vous êtes familier avec le Swing, le premier est équivalent à SwingUtilities.invokeLater
et le second à la notion de SwingWorker
.
le javadoc de la tâche donne de nombreux exemples qui devraient clarifier comment ils peuvent être utilisés. Vous pouvez également vous référer à le tutoriel sur la concurrence .
il peut maintenant être changé en version lambda
@Override
public void actionPerformed(ActionEvent e) {
Platform.runLater(() -> {
try {
//an event with a button maybe
System.out.println("button is clicked");
} catch (IOException | COSVisitorException ex) {
Exceptions.printStackTrace(ex);
}
});
}
l'Une des raisons pour utiliser un explicite Plate-forme.runLater () pourrait être que vous liiez une propriété de l'ui à une propriété de service (résultat). Ainsi, si vous mettez à jour la propriété bound service, vous devez le faire via runLater ():
en UI thread aussi connu sous le nom de JavaFX application thread:
...
listView.itemsProperty().bind(myListService.resultProperty());
...
dans la mise en œuvre des Services en arrière-plan (travailleurs):
...
Platform.runLater(() -> result.add("Element " + finalI));
...