IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
logo

FAQ JavaFXConsultez toutes les FAQ

Nombre d'auteurs : 4, nombre de questions : 507, derni�re mise � jour : 2 novembre 2016  Ajouter une question

 

Cette FAQ a �t� r�alis�e � partir des questions fr�quemment pos�es sur le forum JavaFX de http://java.developpez.com ainsi que l'exp�rience personnelle des auteurs.

Nous tenons � souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne pr�tend pas non plus �tre compl�te. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant r�dacteur, lisez ceci.

Sur ce, nous vous souhaitons une bonne lecture.

SommaireConcurrence (19)
pr�c�dent sommaire suivant
 

JavaFX utilise trois threads principaux :

  • le JavaFX Application Thread - il s'agit du thread �v�nementiel de l'interface graphique, du SceneGraph et de la sc�ne. Les n�uds graphiques qui sont attach�s � une sc�ne ne peuvent �tre manipul�s que dans ce thread. Ce thread est celui dans lequel vous travaillerez et dans lequel votre code s�ex�cutera la plupart du temps ;
  • le thread de rendu Prism - il s'agit du thread qui est utilis� pour effectuer le moteur de rendu Prism qui se charge du rendu � l��cran. Ce thread n'est normalement pas directement accessible au programmeur ;
  • le thread m�dia - ce thread qui tourne en t�che de fond et est utilis� pour synchroniser l�affichage en mettant � jour, par exemple, les intervalles (�tapes interm�diaires) lors d'animations et de transitions. Ce thread n'est normalement pas directement accessible au programmeur.

Mis � jour le 1er octobre 2014 bouye

Il peut arriver que vous ayez besoin d'effectuer une t�che de longue dur�e (traitement long, lecture/�criture de fichier, vous connecter � une base de donn�es, � un web service, etc.). JavaFX met � disposition, dans le package javafx.concurrent, une API de concurrence qui permet de g�rer de telles t�ches sans pour autant bloquer le JavaFX Application Thread.

Pour utiliser cette API de concurrence, vous allez devoir utiliser des objets d'un des trois types suivants :

  • Service<V> - qui est une classe service � manipuler depuis votre UI, dans le JavaFX Application Thread. Une instance de la classe Service peut �tre r�utilis�e plusieurs fois.
  • ScheduledService<V> - qui est une classe service � manipuler depuis votre UI, dans le JavaFX Application Thread. Ce genre de service s�ex�cute de mani�re cyclique � intervalles r�guliers - JDK8 ou ult�rieur.
  • Task<V> - qui est la classe qui se chargera d�ex�cuter la t�che de longue dur�e. Elle s�ex�cutera dans son propre thread, sans interf�rer ni bloquer le JavaFX Application Thread. Une instance de la classe Task ne peut �tre utilis�e qu'une seule et unique fois. La t�che est cr��e par le service.


Ces trois classes impl�mentent l'interface javafx.concurrent.Worker<V>.

Ici, le type V est le type de retour de la t�che et du service. Un service ou une t�che qui ne produit rien sera de type java.lang.Void avec pour valeur de retour la valeur null (la seule valeur accept�e pour ce type).

Mis � jour le 15 mars 2015 bouye

Pour cr�er une t�che de fond, depuis notre IU (par exemple en r�ponse � un clic sur un bouton), nous allons cr�er une instance de la classe abstraite Service<V> avec le type de retour appropri�. Nous allons ensuite surcharger la m�thode createTask() de mani�re � initialiser une instance de la classe abstraite Task<V>. Dans cette t�che, nous allons surcharger la m�thode�call() pour effectuer le traitement de longue dur�e. Le r�sultat du traitement sera retourn� en fin de m�thode.

Par exemple :

Code Java : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final Service<Integer> service = new Service<Integer>() { 
  
    @Override 
    protected Task<Integer> createTask() { 
        return new Task<Integer>() { 
  
            @Override 
            protected Integer call() throws Exception { 
                int result = 0; 
                // Faire le traitement ici. 
                return result; 
            }                             
        }; 
    }                     
};

Ici, nous avons cr�� un service et une t�che qui produisent une valeur enti�re.

Dans le cas o� nous ne produisons rien, il faut proc�der comme suit :

Code Java : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
final Service<Void> service = new Service<Void>() { 
  
    @Override 
    protected Task<Void> createTask() { 
        return new Task<Void>() { 
  
            @Override 
            protected Void call() throws Exception { 
                // Faire le traitement ici. 
                return null; 
            }                             
        }; 
    }                     
};

Ici, null est la seule valeur utilisable avec le type java.lang.Void.

Mis � jour le 2 octobre 2014 bouye

Il est possible de surveiller les changements d��tat d'un service en pla�ant un �couteur de type InvalidationListener ou ChangeListener sur sa propri�t� state.



Cette propri�t�, de type Worker.State, peut avoir les �tats suivants :

  • READY - le service est pr�t � �tre lanc� : il vient d��tre cr�� ou il a �t� r�initialis� ;
  • SCHEDULED - le service a �t� lanc�, mais n'a pas encore d�marr� ;
  • RUNNING - le service a d�marr�, le traitement est en cours ;
  • CANCELLED - le service a �t� annul� ;
  • FAILED - le service a �chou� (ex. : une exception a �t� lanc�e au cours du traitement) ;
  • SUCCEEDED - le service s'est termin� sans erreur. Il est possible d'acc�der au r�sultat du traitement ou de relancer le service.


Par exemple :

Code Java : S�lectionner tout
1
2
3
4
5
service.stateProperty().addListener(observable -> { 
    switch (service.getState()) { 
        // Traiter les diff�rents cas ici. 
    } 
});

Les modifications de valeur seront re�ues sur le JavaFX Application Thread.

La classe Service<V> dispose aussi de callbacks qu'il est possible d'invoquer quand le service change d��tat :

  • setOnReady() - le service est pass� dans l��tat READY ;
  • setOnScheduled() - le service est pass� dans l��tat SCHEDULED ;
  • setOnRunning() - le service est pass� dans l��tat RUNNING ;
  • setOnCancelled() - le service est pass� dans l��tat CANCELLED ;
  • setOnFailed() - le service est pass� dans l��tat FAILED ;
  • setOnSucceeded() - le service est pass� dans l��tat SUCCEEDED.


Ces callback prennent un param�tre de type EventHandler<WorkerStateEvent>.

Par exemple :

Code Java : S�lectionner tout
1
2
3
4
5
6
7
service.setOnSucceeded(new EventHandler<WorkerStateEvent>() { 
  
    @Override 
    public void handle(WorkerStateEvent workerStateEvent) { 
        System.out.println("Traitement termin� !"); 
    } 
});

Ou :

Code Java : S�lectionner tout
service.setOnSucceeded(workerStateEvent -> System.out.println("Traitement termin� !"));

Mis � jour le 2 octobre 2014 bouye

Il est possible de surveiller les changements d��tat d'une t�che en pla�ant un �couteur de type InvalidationListener ou ChangeListener sur sa propri�t� state.



Cette propri�t�, de type Worker.State, peut avoir les �tats suivants :

  • READY - la t�che est pr�te � �tre lanc�e : elle vient d��tre cr��e ;
  • SCHEDULED - la t�che a �t� lanc�e, mais n'a pas encore d�marr� ;
  • RUNNING - la t�che a d�marr�, le traitement est en cours ;
  • CANCELLED - la t�che a �t� annul�e ;
  • FAILED - la t�che a �chou� (ex. : une exception a �t� lanc�e au cours du traitement) ;
  • SUCCEEDED - la t�che s'est termin�e sans erreur. Il est possible d'acc�der au r�sultat du traitement.


Par exemple :

Code Java : S�lectionner tout
1
2
3
4
5
task.stateProperty().addListener(observable -> { 
    switch (task.getState()) { 
        // Traiter les diff�rents cas ici. 
    } 
});

Les modifications de valeur seront re�ues sur le JavaFX Application Thread.

La classe Task<V> dispose aussi de callbacks qu'il est possible d'invoquer quand la t�che change d��tat :

  • setOnScheduled() - le service est pass� dans l��tat SCHEDULED ;
  • setOnRunning() - le service est pass� dans l��tat RUNNING ;
  • setOnCancelled() - le service est pass� dans l��tat CANCELLED ;
  • setOnFailed() - le service est pass� dans l��tat FAILED ;
  • setOnSucceeded() - le service est pass� dans l��tat SUCCEEDED.


Ici, il n'existe pas de callback setOnReady(), car la t�che est dans l��tat READY d�s sa cr�ation. De plus, une t�che ne peut pas �tre r�utilis�e et donc elle ne peut plus jamais revenir � cet �tat apr�s son lancement.

Ces callback prennent un param�tre de type EventHandler<WorkerStateEvent>.

Par exemple :

Code Java : S�lectionner tout
1
2
3
4
5
6
7
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() { 
  
    @Override 
    public void handle(WorkerStateEvent workerStateEvent) { 
        System.out.println("Traitement termin� !"); 
    } 
});

Ou :

Code Java : S�lectionner tout
task.setOnSucceeded(workerStateEvent -> System.out.println("Traitement termin� !"));

Mis � jour le 2 octobre 2014 bouye

Pour d�marrer un service, il suffit d'invoquer la m�thode start() de ce service.

Par exemple :

Code Java : S�lectionner tout
service.start();

Cela aura pour effet de cr�er une nouvelle instance de la t�che, puis de la placer � l��tat SCHEDULED. La t�che sera alors ex�cut�e dans un autre thread ce qui placera la t�che et le service dans l��tat RUNNING. Lorsque la t�che se terminera, elle atteindra l��tat CANCELLED, FAILED ou SUCCEEDED qui sera transmis au service. Cette m�thode ne doit �tre invoqu�e que depuis le JavaFX Application Thread.

Une exception sera lev�e si le service n'est pas dans l��tat READY lorsque la m�thode start() est invoqu�e.

Mis � jour le 2 octobre 2014 bouye

Pour annuler un service, il suffit d'invoquer la m�thode cancel() de ce service.

Par exemple :

Code Java : S�lectionner tout
service.cancel();

Cette m�thode retourne la valeur true lorsque le service a pu changer d��tat. Elle retournera false si le service est d�j� dans l��tat CANCELLED ou s'il est dans l��tat SUCCEEDED.

Invoquer cette m�thode ne stoppe pas imm�diatement la t�che, elle positionne juste un s�maphore qui indique � la t�che qu'elle doit s�arr�ter.

Mis � jour le 2 octobre 2014 bouye

Pour savoir si une t�che a �t� annul�e, le programmeur doit r�guli�rement tester la valeur de retour de la m�thode isCancelled() de la t�che durant son traitement. Si cette m�thode retourne true, c'est que la t�che a �t� annul�e et que le traitement doit �tre interrompu.

Par exemple, le code suivant est une t�che qui teste si un nombre donn� est premier :

Code Java : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class PrimeTestTask extends Task<Boolean> { 
  
    private final int value; 
  
    public PrimeTestTask(final int value) { 
        this.value = Math.abs(value); 
    } 
  
    @Override 
    protected Boolean call() throws Exception { 
        Boolean result = Boolean.TRUE; 
        if (value == 0 || value == 1 || (value > 2 && value % 2 == 0)) { 
            result = Boolean.FALSE; 
        } else if (value > 2) { 
            for (int test = 3; test * test < value; test += 2) { 
                // Le traitement a �t� annul�. 
                if (isCancelled()) { 
                    return null; 
                } 
                if (value % test == 0) { 
                    result = Boolean.FALSE; 
                    break; 
                } 
            } 
        } 
        return result; 
    } 
}

Ici, lorsque la m�thode isCancelled() retourne la valeur true, nous retournons une valeur ind�termin�e et nous sortons de la t�che.

Mis � jour le 2 octobre 2014 bouye

Pour pouvoir red�marrer un service, il faut que ce dernier soit � nouveau dans un �tat READY. Il est possible de r�initialiser la valeur de cet �tat en appelant la m�thode reset() du service.



Par exemple :

Code Java : S�lectionner tout
service.reset();

Si cette m�thode est invoqu�e alors que le service n'est pas dans l��tat READY, CANCELLED, FAILED ou SUCCEEDED, une exception sera lev�e. Cette m�thode ne doit �tre invoqu�e que depuis le JavaFX Application Thread.

Une fois ceci fait, il est � nouveau possible d'invoquer la m�thode start() du service.

Il est �galement possible d'invoquer la m�thode de convenance restart().

Par exemple :

Code Java : S�lectionner tout
service.restart();

Ce qui aura pour effet de red�marrer compl�tement le service. Cette m�thode ne doit �tre invoqu�e que depuis le JavaFX Application Thread.

Invoquer cette m�thode est l��quivalent d'invoquer successivement :

Code Java : S�lectionner tout
1
2
3
service.cancel(); 
service.reset(); 
service.start();

Mis � jour le 2 octobre 2014 bouye

Il est possible d'envoyer des notifications durant un traitement long. La classe Task<V> dispose de quatre m�thodes destin�es � cet effet, et qui peuvent �tre invoqu�es directement depuis le code s�ex�cutant dans la m�thode call() de la t�che :

  • updateMessage() - permet de faire remonter un message textuel ;
  • updateProgress() - permet d'indiquer l��tat d'avancement du traitement. Cette m�thode prend deux valeurs en param�tres, l'avancement actuel et l'avancement total. Un avancement n�gatif ou invalide (infinit� ou NaN) r�sultera en une valeur de progression ind�termin�e ;
  • updateTitle() - permet de modifier l�intitul� du traitement ;
  • updateValue() - permet de modifier la valeur de retour de la t�che pour sp�cifier une valeur interm�diaire - JDK8 ou ult�rieur.


Invoquer ces m�thodes permet de mettre � jour de mani�re asynchrone les propri�t�s �quivalentes message, progress, title et value de la t�che et de son service parent. Pour �viter une gestion d��v�nement trop lourde, ces m�thodes fusionnent les appels en cas d'invocations successives trop rapproch�es pour ne conserver que la derni�re valeur : certaines valeurs interm�diaires peuvent donc �tre omises et ne pas �tre r�percut�es sur les propri�t�s.

  • message - le dernier message post�.
  • progress - le dernier �tat d'avancement du traitement. Cette valeur est initialement � 0. Une valeur de 1 indique normalement que le traitement est termin�. Une valeur de -1 indique que l'avancement est ind�termin�.
  • title - le dernier intitul� du traitement.
  • value - la derni�re valeur du traitement. Cette propri�t� sera �galement affect�e � la valeur de retour de la t�che � la fin du traitement.


Il est donc possible de construire des IU permettant de suivre l'avancement d'un traitement en effectuant du binding sur ces propri�t�s.

Par exemple :

Code Java : S�lectionner tout
1
2
3
titleLabel.textProperty().bind(service.titleProperty()); 
progressLabel.textProperty().bind(service.messageProperty()); 
progressBar.progressProperty().bind(service.progressProperty());

Ici, les labels contenant l'intitul� et le message du traitement, de m�me que la barre de progression se mettront automatiquement � jour.

Mis � jour le 2 octobre 2014 bouye

Pour r�cup�rer le r�sultat final d'un service, il suffit de r�cup�rer la valeur de sa propri�t� en lecture seule value lorsque le service est dans l��tat SUCCEEDED.

Par exemple :

Code Java : S�lectionner tout
1
2
3
4
service.setOnSucceeded(workerStateEvent -> { 
    final V result = service.getValue(); 
    System.out.printf("Traitement termin� %s !", result).println(); 
});

Mis � jour le 2 octobre 2014 bouye

Pour connaitre les causes de l��chec d'un service, il faut r�cup�rer la valeur de sa propri�t� en lecture seule exception lorsque le service est dans l��tat FAILED. Cette propri�t� contient une valeur de type java.lang.Throwable.

Par exemple :

Code Java : S�lectionner tout
1
2
3
4
service.setOnFailed(workerStateEvent -> { 
     System.err.println("�chec du service !"); 
     service.getException().printStackTrace(); 
});

Mis � jour le 2 octobre 2014 bouye

Depuis le JDK 8, pour cr�er une t�che de fond r�p�table, depuis notre IU (par exemple en r�ponse � un clic sur un bouton), nous allons cr�er une instance de la classe abstraite ScheduledService<V> avec le type de retour appropri�. Nous allons ensuite surcharger la m�thode createTask() de mani�re � initialiser une instance de la classe abstraite Task<V>. Dans cette t�che, nous allons surcharger la m�thode call() pour effectuer le traitement de longue dur�e. Le r�sultat du traitement sera retourn� en fin de m�thode.

Par exemple :

Code Java : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final ScheduledService<Integer> service = new ScheduledService<Integer>() { 
  
    @Override 
    protected Task<Integer> createTask() { 
        return new Task<Integer>() { 
  
            @Override 
            protected Integer call() throws Exception { 
                int result = 0; 
                // Faire le traitement ici. 
                return result; 
            }                             
        }; 
    }                     
};

Ici, nous avons cr�� un service et une t�che qui produisent une valeur enti�re.

Dans le cas o� nous ne produisons rien, il faut proc�der comme suit :

Code Java : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
final ScheduledService<Void> service = new ScheduledService<Void>() { 
  
    @Override 
    protected Task<Void> createTask() { 
        return new Task<Void>() { 
  
            @Override 
            protected Void call() throws Exception { 
                // Faire le traitement ici. 
                return null; 
            }                             
        }; 
    }                     
};

Ici, null est la seule valeur utilisable avec le type java.lang.Void.

Un ScheduledService se cr�e et se manipule donc de mani�re similaire � un Service simple. Cependant il y a une diff�rence majeure : un Service s�ex�cute une seule et unique fois (mais peut �tre relanc� ult�rieurement) tandis qu'un ScheduledService se r�p�te automatiquement apr�s un d�lai lors que son ex�cution a �t� couronn�e de succ�s. Le programmeur peut �galement contr�ler si le service est autoris� � se relancer en cas d��chec. Par d�faut, un service r�p�table s�arr�te lorsque son ex�cution �choue.

Mis � jour le 15 mars 2015 bouye

Pour diff�rer le lancement d'une t�che de fond r�p�table, vous devez sp�cifier une valeur de type javafx.util.Duration dans la propri�t� delay de votre instance de la classe ScheduledService<V>.

Par exemple :

Code Java : S�lectionner tout
1
2
service.setDelay(Duration.seconds(5)); 
service.start();

Ici, le service d�marrera apr�s cinq secondes d'attente.

Mis � jour le 15 mars 2015 bouye

Pour autoriser une t�che de fond r�p�table � se relancer en cas d��chec, vous devez modifier la valeur de la propri�t� restartOnFailure de l'instance de la classe ScheduledService<V> et lui donner la valeur true.

Par exemple :

Code Java : S�lectionner tout
service.setRestartOnFailure(true);

Ici, le service se r�p�tera m�me en cas d��chec.

Mis � jour le 15 mars 2015 bouye

Pour limiter le nombre de r�p�titions d'une t�che de fond r�p�table en cas d��chec, vous devez modifier la valeur de sa propri�t� maxFailureCount.

Par exemple :

Code Java : S�lectionner tout
service.setMaxFailureCount(100);

Ici, notre service s�arr�tera de lui-m�me apr�s le centi�me �chec.

Mis � jour le 15 mars 2015 bouye

Pour connaitre le nombre d��checs d'une t�che de fond r�p�table, vous pouvez interroger sa propri�t� en lecture seule currentFailureCount. Cette propri�t� contient le nombre d��checs du service depuis son lancement initial. Ce nombre sera r�initialis� � z�ro si le service est manuellement red�marr�.

Par exemple :

Code Java : S�lectionner tout
final int failureNumber = service.getCurrentFailureCount();

Mis � jour le 15 mars 2015 bouye

Pour sp�cifier la p�riode d'une t�che de fond r�p�table, vous devez sp�cifier une valeur de type javafx.util.Duration dans la propri�t� period de votre instance de la classe ScheduledService<V>. Il s'agit de la p�riode de temps qui s��coule entre deux moments durant lesquels le service passe dans un �tat RUNNING lors d'une ex�cution couronn�e de succ�s.

Code Java : S�lectionner tout
service.setPeriod(Duration.seconds(1));

Ici, nous avons indiqu� que notre service doit se r�p�ter toutes les secondes.

Le service ne peut interrompre une t�che en cours, donc cette derni�re continuera de s�ex�cuter m�me si le temps sp�cifi� dans la p�riode est d�pass�. Si la t�che prend plus de temps que la p�riode � s�ex�cuter ou si la p�riode est vide (Duration.ZERO ou dur�e non d�finie), le service s�ex�cutera � nouveau imm�diatement apr�s que la t�che se soit termin�e sans attendre.

En cas d��chec du service, il est possible d'ajouter un temps d'attente suppl�mentaire en fournissant une fabrique � dur�es, de type Callback<ScheduledService<?>, Duration> dans sa propri�t� backoffStrategy. Cette fabrique n'est invoqu�e que lorsque l�ex�cution du service �choue. Cela permet, par exemple, d'augmenter le temps d'attente entre chaque tentative de connexion qui n'est pas couronn�e de succ�s :

Code Java : S�lectionner tout
1
2
3
4
5
6
service.setBackoffStrategy(new Callback<ScheduledService<?>, Duration>() { 
  
    public Duration call(ScheduledService<?> service) { 
        return Duration.seconds(service.getCurrentFailureCount() * 5); 
    } 
});

Ou :

Code Java : S�lectionner tout
service.setBackoffStrategy(service -> Duration.seconds(service.getCurrentFailureCount() * 5));

Ici, pour chaque ex�cution qui a �chou�, le service attendra cinq secondes suppl�mentaires avant de tenter � nouveau de s�ex�cuter.

Le temps sp�cifi� dans la propri�t� period et le temps additionnel en cas d��chec (qui est de z�ro en cas d�ex�cution correcte) forment la p�riode cumul�e qui est le temps effectif entre chaque passage du service dans l��tat RUNNING. Cette valeur peut �tre consult�e via la propri�t� en lecture seule cumulativePeriod.

Il est possible de plafonner la p�riode cumul�e en sp�cifiant une valeur de type Duration dans la propri�t� maximumCumulativePeriod.

Par exemple :

Code Java : S�lectionner tout
service.setMaximumCumulativePeriod(Duration.minutes(10));

Ici, la p�riode cumul�e sera d'au maximum 10 minutes.

Mis � jour le 15 mars 2015 bouye

Lorsqu'une t�che de fond r�p�table se relance, sa propri�t� value est r�initialis�e avec la valeur null. Cependant la propri�t� en lecture seule lastValue conserve le r�sultat de la derni�re bonne ex�cution du service.

Par exemple :

Code Java : S�lectionner tout
final Integer lastResult = service.getLastValue();

Avant le premier lancement du service, cette propri�t� contient la valeur null.

Mis � jour le 15 mars 2015 bouye

Proposer une nouvelle r�ponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plut�t sur le forum de la rubrique pour �a


R�ponse � la question

Liens sous la question
pr�c�dent sommaire suivant
 

Les sources pr�sent�es sur cette page sont libres de droits et vous pouvez les utiliser � votre convenance. Par contre, la page de pr�sentation constitue une �uvre intellectuelle prot�g�e par les droits d'auteur. Copyright � 2025 Developpez Developpez LLC. Tous droits r�serv�s Developpez LLC. Aucune reproduction, m�me partielle, ne peut �tre faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'� trois ans de prison et jusqu'� 300 000 � de dommages et int�r�ts.