
Envoyé par
nouknouk
D'ou l'idée de dire qu'il n'y a qu'un seul thread qui va traiter les événements, l'EDT ; quand je poste un événement celui ci sera systématiquement traité par l'EDT et personne d'autre, que l'événement provienne d'une action de l'utilisateur, d'une socket ou de quoi que ce soit d'autre.
Un seul thread devra traiter les événements : OK !
Mais pourquoi l'EDT ???? Son objectif est de traiter les évènements graphiques et l'affichage. Pourquoi l'encombrer encore avec d'autres traitements qui pourraient poser des problèmes d'affichage ?
Pourquoi ne pas utiliser un thread spécifique c'est bien plus simple...
Tu as (au moins) deux possibilités assez simple, utiliser une BlockingQueue pour passer les données (les deux exemples utilise le design pattern Singleton) :
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| class ModelThreadQueue {
private final static ModelThreadQueue instance = new ModelThreadQueue();
private BlockingQueue<Data> queue = new LinkedBlockingQueue<Data>();
// Thread principale qui s'occupera de traiter les données
private final Thread thread;
// Constructeur privée (pour éviter les doublons)
private ModelThreadQueue() {
// On lance le thread de traitement des données
this.thread = new Thread("ModelThread") {
@Override
public void run() {
takeData();
}
};
this.thread.start();
}
// Accesseur public (voir DP du Singleton)
public static ModelThreadQueue getInstance() {
return instance;
}
private void takeData() {
try {
while (true) {
// Traitement des données de data
callbackFonction( queue.take() );
}
} catch (InterruptedException e) {
// Interruption : fin du thread
e.printStackTrace();
}
}
public void callback(Data data) {
// On ajoute les données dans la queue,
// elle seront traité dès que possible par
this.queue.offer(data);
}
private void callbackFonction(Data data) {
// Traitement des données
// (méthode appelé en interne)
}
} |
Soit Data les données passées à la méthode callback(). Lorsqu'elle est appelé, l'objet est ajouté dans une queue FIFO (et thread-safe bien sûr) et la méthode retourne immédiatement. Le thread (lancé dans le constructeur) récupèrera les données de la queue afin de les traiter au fur et à mesure.
Dans tes SocketThread, il suffira de faire quelque chose du style :
ModelThreadQueue.getInstance().callback( data );
Seconde solution, tu peux utiliser un Executor afin de passer directement des objets Runnable et ainsi avoir un fonctionnement "proche" de celui de l'EDT...
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 29 30 31
| class ModelThreadExecutor {
private final static ModelThreadExecutor instance = new ModelThreadExecutor();
private Executor executor = Executors.newSingleThreadExecutor();
// Constructeur privée (pour éviter les doublons)
private ModelThreadExecutor() {
}
// Accesseur public (voir DP du Singleton)
public static ModelThreadExecutor getInstance() {
return instance;
}
public void invokeLater(Runnable r) {
executor.execute(r);
}
public void callback(final Data data) {
invokeLater(new Runnable() {
public void run() {
// Traitement des données :
callbackFonction(data);
}
});
}
private void callbackFonction(Data data) {
// Traitement des données
// (méthode appelé en interne)
}
} |
Ici on utilise un executor qui utilise un thread unique afin de garantir l'unicité de l'accès aux données (et qui est automatiquement recrée s'il "meurt"), et la méthode invokeLater() permet de lui passer des traitements (comme le montre l'exemple avec la méthode callback() ).
Et il y a encore plusieurs autres manières de faire sans monopoliser l'EDT... 
a++
Partager