Salut! En tant que fournisseur NIO, j'ai plongé profondément dans le monde des E/S asynchrones Java NIO, et aujourd'hui, je suis ravi de partager avec vous comment utiliser CompletionHandler dans les E/S asynchrones Java NIO. C'est un concept plutôt sympa qui peut vraiment améliorer votre jeu de programmation, en particulier lorsqu'il s'agit d'opérations d'E/S hautes performances.
Tout d’abord, comprenons ce que sont les E/S asynchrones Java NIO. Dans les E/S Java traditionnelles, les opérations sont bloquantes. Cela signifie que lorsque vous effectuez une opération d'E/S comme la lecture d'un fichier ou l'obtention de données à partir d'un socket réseau, votre programme doit attendre que cette opération soit terminée avant de pouvoir passer à la tâche suivante. Cela peut être un véritable frein, en particulier dans une application à fort trafic où vous ne voulez pas que votre programme reste bloqué en attente.
Les E/S asynchrones Java NIO, en revanche, permettent à votre programme de continuer à effectuer d'autres tâches pendant que l'opération d'E/S est en cours. Il utilise une approche basée sur le rappel ou basée sur le futur pour avertir votre programme lorsque l'opération est terminée. Et c'est là qu'intervient CompletionHandler.
Un CompletionHandler est une interface dans Java NIO qui définit deux méthodes :complétéetéchoué. LecomplétéLa méthode est appelée lorsque l’opération d’E/S asynchrone se termine avec succès et vous donne accès au résultat de l’opération. LeéchouéLa méthode est appelée si quelque chose ne va pas pendant l’opération et fournit des informations sur l’erreur.
Commençons par un exemple simple d'utilisation de CompletionHandler pour la lecture de fichiers asynchrone.
importer java.nio.ByteBuffer ; importer java.nio.channels.AsynchronousFileChannel ; importer java.nio.channels.CompletionHandler ; importer java.nio.file.Path ; importer java.nio.file.Paths ; importer java.nio.file.StandardOpenOption ; public class AsyncFileReadExample { public static void main(String[] args) { Path path = Paths.get("test.txt"); essayez (AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ)) { ByteBuffer buffer = ByteBuffer.allocate(1024); fileChannel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public voidcomplete(Integer result, ByteBuffer attachment) { System.out.println("Read " + result + " bytes"); buffer.flip(); byte[] data = new byte[buffer.limit()]; buffer.get(data); System.out.println(new String(data)); } @Override public void failed (Throwable exc, ByteBuffer attachment) { System.err.println("Read failed: " + exc.getMessage() } }); // Effectuer d'autres tâches pendant que l'opération de lecture est en cours System.out.println("Faire d'autres tâches..."); Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } } }
Dans cet exemple, nous ouvrons d'abord unAsynchronousFileChannelpour la lecture. Ensuite, nous attribuons unOctetBufferpour contenir les données que nous allons lire. Nous appelons lelireméthode sur le canal de fichier, en passant dans le tampon, la position à partir de laquelle commencer la lecture (dans ce cas, 0), une pièce jointe (qui peut être n'importe quel objet que vous souhaitez transmettre avec l'opération) et une instance de notreGestionnaire d'achèvement.


Lecomplétéméthode dans leGestionnaire d'achèvementest appelé lorsque l’opération de lecture réussit. Il imprime le nombre d'octets lus, retourne le tampon, puis imprime le contenu du tampon sous forme de chaîne. LeéchouéLa méthode est appelée s’il y a une erreur lors de l’opération de lecture et imprime un message d’erreur.
Pendant que l'opération de lecture est en cours, notre programme peut continuer à effectuer d'autres tâches. Dans cet exemple simple, nous imprimons simplement un message, puis dormons pendant quelques secondes.
Parlons maintenant de l'utilisation de CompletionHandler pour les E/S réseau. Supposons que vous construisiez une application client-serveur et que vous souhaitiez gérer les connexions entrantes de manière asynchrone.
importer java.io.IOException ; importer java.net.InetSocketAddress ; importer java.nio.ByteBuffer ; importer java.nio.channels.AsynchronousServerSocketChannel ; importer java.nio.channels.AsynchronousSocketChannel ; importer java.nio.channels.CompletionHandler ; public class AsyncServerExample { public static void main(String[] args) { try (AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open()) { serverSocketChannel.bind(new InetSocketAddress(8080)); System.out.println("Serveur démarré sur le port 8080"); serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() { @Override public void terminé (AsynchronousSocketChannel clientChannel, Void attachment) { serverSocketChannel.accept(null, this); System.out.println("Nouveau client connecté"); ByteBuffer buffer = ByteBuffer.allocate(1024); clientChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public voidcomplete(Integer result, ByteBuffer attachment) { if (result > 0) { attachment.flip(); byte[] data = new byte[attachment.limit()]; attachment.get(data); String message = new String(data); System.out.println("Received: " + message); try { clientChannel.write(ByteBuffer.wrap(("Vous avez envoyé : " + message).getBytes())).get(); } catch (Exception e) { e.printStackTrace(); } } try { clientChannel.close(); } catch (IOException e) { e.printStackTrace(); } } @Override public void failed (Throwable exc, ByteBuffer attachment) System.err.println("Échec de la lecture : " + exc.getMessage()); try { clientChannel.close(); } catch (IOException e) { e.printStackTrace(); } } }); // Maintenir le serveur en cours d'exécution Thread.sleep(Long.MAX_VALUE); } catch (Exception e) { e.printStackTrace(); } } }
Dans cet exemple de serveur, nous ouvrons unAsynchronousServerSocketChannelet liez-le au port 8080. Ensuite, nous appelons leaccepterméthode sur le canal de socket du serveur, en passant unGestionnaire d'achèvement. Lorsqu'un nouveau client se connecte, lecomplétéméthode duGestionnaire d'achèvementest appelé. Dans cette méthode, nous acceptons une autre connexion (afin que le serveur puisse gérer plusieurs clients), imprimons un message indiquant qu'un nouveau client s'est connecté, puis commençons à lire les données du client.
Nous en utilisons un autreGestionnaire d'achèvementpour l'opération de lecture. Si la lecture réussit, nous imprimons le message reçu et renvoyons une réponse au client. S'il y a une erreur, nous imprimons un message d'erreur et fermons le canal client.
L'un des avantages de l'utilisation de CompletionHandler dans les E/S asynchrones Java NIO est qu'il vous permet de gérer plusieurs opérations d'E/S simultanément sans bloquer votre programme. Cela peut conduire à des applications beaucoup plus efficaces et réactives, en particulier dans les scénarios où vous avez un grand nombre de clients ou des transferts de données à volume élevé.
Si vous aimez les voitures électriques, vous pourriez être intéressé parVoiture électrique Nio ET5. Il s'agit d'un véhicule électrique élégant et hautes performances qui combine style et technologie, tout comme CompletionHandler combine efficacité et flexibilité dans les E/S asynchrones Java NIO.
En tant que fournisseur NIO, je connais l'importance des systèmes performants et fiables. Que ce soit dans l'industrie automobile ou dans la programmation de logiciels, nous sommes toujours à la recherche de moyens d'optimisation et d'amélioration. Si vous souhaitez en savoir plus sur les E/S asynchrones Java NIO ou si vous avez des besoins liés à nos produits et services, n'hésitez pas à nous contacter. Nous sommes là pour vous aider à faire passer vos projets au niveau supérieur. Discutons de la manière dont nous pouvons travailler ensemble pour répondre à vos exigences.
Références :
- Documentation JavaNIO
- Divers tutoriels et blogs de programmation en ligne



























































