Récemment, j'écris un outil de téléchargement FTP et j'utilise FTPClient d'Apache. Afin d'améliorer l'efficacité du téléchargement, j'ai adopté une approche multithread, mais la création et la destruction fréquentes d'objets FTPClient par chaque fil provoquera inévitablement des frais généraux inutiles. Par conséquent, il est préférable d'utiliser un pool de connexion FTPClient ici. J'ai soigneusement parcouru l'API Apache et j'ai constaté qu'il n'avait pas d'implémentation de FTPClientPool, j'ai donc dû écrire moi-même un ftpclientpool. Ce qui suit présentera l'ensemble du processus de développement d'un pool de connexion pour votre référence.
À propos de la piscine d'objets
Certains objets ont des frais généraux relativement élevés, tels que les connexions de la base de données. Afin de réduire la consommation de performances causée par la création et la destruction fréquentes des objets, nous pouvons utiliser la technologie de la mise en commun d'objets pour réaliser une réutilisation des objets. Object Pool fournit un mécanisme qui peut gérer le cycle de vie des objets dans le pool d'objets, fournit une méthode pour obtenir et libérer des objets, et permet aux clients d'utiliser facilement des objets dans le pool d'objets.
Si nous voulons mettre en œuvre un pool d'objets nous-mêmes, nous devons généralement remplir les fonctions suivantes:
1. S'il y a des objets disponibles dans le pool, le pool d'objets doit pouvoir retourner au client.
2. Après que le client ait remis les objets dans la piscine, ils peuvent les réutiliser.
3. Les pools d'objets peuvent créer de nouveaux objets pour répondre aux besoins croissants des clients
4. Il y a un mécanisme pour fermer correctement la piscine pour mettre fin au cycle de vie de l'objet
Boîte à outils d'objet d'Apache
Afin de nous faciliter de développer notre propre pool d'objets, la boîte à outils commun fournie par Apache contient certaines interfaces et des classes d'implémentation pour développer des pools d'objets communs. Les deux interfaces les plus basiques sont ObjectPool et PoolableObjectFactory.
Il existe plusieurs méthodes de base dans l'interface ObjectPool:
1. AddObject (): Ajouter un objet à la piscine
2. BorrowObject (): Le client emprunte un objet à la piscine
3. ReturnObject (): Le client renvoie un objet au pool
4. Close (): Fermez le pool d'objets, nettoyez la mémoire et les ressources de libération, etc.
5. SetFactory (objetFactory Factory): Une usine est nécessaire pour créer des objets dans le pool.
Plusieurs méthodes de base dans l'interface PoolableObjectFactory:
1. MakeObject (): Faire un objet
2. DestoryObject (): Détruisez un objet
3. ValidateObject (): Vérifiez si un objet est toujours disponible
Grâce aux deux interfaces ci-dessus, nous pouvons implémenter un pool d'objets par nous-mêmes.
Exemple: développer un pool d'objets FTPClient
Récemment, un projet est en cours de développement qui nécessite le téléchargement de fichiers dans HDFS vers un groupe de serveurs FTP. Afin d'améliorer l'efficacité du téléchargement, nous envisageons naturellement d'utiliser des méthodes multipliées pour le téléchargement. L'outil que j'ai téléchargé FTP est le FTPClient dans le package Apache Common Nett, mais Apache ne fournit pas FTPClientPool. Ainsi, afin de réduire le nombre de fois où le FTPClient est créé et détruit, nous avons développé un FTPClientPool nous-mêmes pour réutiliser la connexion FTPClient.
Grâce à l'introduction ci-dessus, nous pouvons utiliser le package commun fourni par Apache pour nous aider à développer des pools de connexion. Pour développer un pool d'objets simples, il vous suffit d'implémenter les interfaces ObjectPool et PoorableObjectFactory dans le package de pool commun. Jetons un coup d'œil à la mise en œuvre que j'ai écrite:
Écrivez une implémentation d'interface ObjectPool ftpclientpool
Importer java.io.ioException; import java.util.nosuchelementException; import java.util.concurrent.arrayblockingqueue; import java.util.concurrent.blockerqueue; import java.util.concurrent.timenit; import org.apache.commons.pool.objectpool; import org.apache.commons.pool.poolableObjectFactory; / *** implémentez un pool de connexion ftpclient * @author heaven * / public class ftpclientpool implémente ObjectPool <ftpclient> {private static final int default_pool_size = 10; Pool BlockingQueue Final Blocking <FTPClient>; usine privée FTPClientFactory; / ** * Initialisation du pool de connexions, une usine doit être injectée pour fournir l'instance ftpclient * @param factory * @throws exception * / public ftpclientpool (ftpclientfactory factory) lève exception {this (default_pool_size, factory); } / ** * * @param maxpoolSize * @param factory * @throws exception * / public ftpclientpool (int poolSize, ftpclientfactory factory) lève exception {this.factory = usine; pool = nouveau ArrayBlockingQueue <ftpClient> (PoolSize * 2); InitPool (PoolSize); } / ** * Initialisation du pool de connexion, une usine doit être injectée pour fournir l'instance ftpclient * @param maxpoolSize * @throws exception * / private void initpool (int maxpoolSize) lève exception {for (int i = 0; i <maxpoolSize; i ++) {// ajouter un objet à la pool addObject (); }} / * (non javadoc) * @see org.apache.commons.pool.objectpool # BorrowObject () * / public ftpclient BorrowObject () lève une exception, nosuchelementException, illégalStateException {ftpclient client = pool.take (); if (client == null) {client = factory.makeObject (); addObject (); } else if (! factory.validateObject (client)) {// Vérifiez de ne pas passer // faire l'objet invalidateObject (client); // fabriquer et ajouter de nouveaux objets au pool client = factory.makeObject (); addObject (); } return client; } / * (non javadoc) * @see org.apache.commons.pool.objectpool # returnObject (java.lang.object) * / public void returnObject (ftpclient client) lève exception {if (client! = null) &&! pool.offer (client, 3, timeunit); } catch (ioException e) {e.printStackTrace (); }}} public void invalidateObject (client ftpclient) lève une exception {// supprimer invalider le client pool.remove (client); } / * (non javadoc) * @see org.apache.commons.pool.objectpool # addObject () * / public void addObject () lève l'exception, illégalStateException, unportedOperationException {// Insérez l'objet à la file d'attente Pool.offer (factory.makeObject (), 3, TimeUnit.Seconds); } public int getNumidle () lève unportedOperationException {return 0; } public int getNumActive () lève unportoperationException {return 0; } public void clear () lève une exception, UnsupportedOperationException {} / * (non javadoc) * @see org.apache.commons.pool.objectpool # close () * / public void close () lance l'exception = while.take.iterator (). Hasnext ()) {ftpclient client = pool.take (); factory.DestROYObject (client); }} public void setFactory (poolableObjectFactory <ftpClient> Factory) lève illégalStateException, UnsupporttedOperationException {}}Écrivez une autre mise en œuvre de l'interface PoorableObjectFactory FTPClientFactory
import java.io.ioException; import org.apache.commons.net.ftp.ftpclient; import org.apache.commons.net.ftp.ftpreply; import org.apache.commons.pool.poolableobjectfactory; com.hdfstoftp.util.ftpclientException; / *** FTPClient Factory Class, fournit la création et la destruction des instances FTPClient via FTPClient Factory * @Author Heaven * / Public Class FTPClientFactory implémente PoolableObjectFactory <FtpClient> {Private STATIC Logger = logger configuration privée ftpclientConfigure; // Pause un objet de paramètre à l'usine pour faciliter la configuration des paramètres pertinents de FTPClient public ftpClientFactory (FTPClientConfigure Config) {this.config = config; } / * (non javadoc) * @see org.apache.commons.pool.poolableObjectFactory # MakeObject () * / public ftpClient makeObject () lève une exception {ftpclient ftpclient = new ftpclient (); ftpClient.setConnectTimeout (config.getClientTimeout ()); essayez {ftpclient.connect (config.Gethost (), config.getport ()); int réponse = ftpclient.getReplyCode (); if (! ftpreply.ispositivecompletion (réponse)) {ftpclient.disconnect (); Logger.Warn ("FtPServer Refused Connection"); retourner null; } boolean result = ftpclient.login (config.getUserName (), config.getPassword ()); if (! Result) {Throw new ftpClientException ("FtpClient Login a échoué! Username:" + config.getUserName () + "; mot de passe:" + config.getPassword ()); } ftpclient.setFileType (config.getTransferFileType ()); ftpClient.setBuffeSize (1024); ftpClient.setControleCcoding (config.getEncoding ()); if (config.getPassiveMode (). equals ("true")) {ftpclient.enterLocalPassiveMode (); }} catch (ioException e) {e.printStackTrace (); } catch (ftpClientException e) {e.printStackTrace (); } return ftpClient; } / * (non javadoc) * @see org.apache.commons.pool.poolableObjectFactory # destrustObject (java.lang.object) * / public void destrustObject (ftpclient ftpclient) exception {try {if (ftpclient! = null && ftpclient.isconnected () {ftpcLe. }} catch (ioException io) {io.printStackTrace (); } Enfin {// Notez que vous devez déconnecter la connexion dans le code enfin, sinon cela entraînera l'occupation de la connexion FTP {ftpClient.disconnect (); } catch (ioException io) {io.printStackTrace (); }}} / * (non javadoc) * @see org.apache.commons.pool.poolableObjectFactory # validateObject (java.lang.object) * / public boolean validateObject (ftpclient ftpclient) {try {return ftpclient.sendNoop (); } catch (ioException e) {lancer une nouvelle RuntimeException ("Échec de la validation du client:" + e, e); }} public void actiateObject (ftpclient ftpclient) lève une exception {} public void passivateObject (ftpclient ftpclient) lève une exception {}}Enfin, il est préférable de transmettre un objet de paramètre à l'usine pour nous faciliter pour définir certains paramètres de ftpclient
package org.apache.commons.pool.impl.contrib; / ** * Classe de configuration FTPClient, encapsule la configuration pertinente de ftpclient * * @author heaven * / public class ftpclientConfigure {private String host; port int privé; Nom d'utilisateur de chaîne privée; mot de passe de chaîne privé; chaîne privée passiveMode; Encodage de chaînes privées; private int clienttimeout; INT PRIVÉ INTRÉE FILDUM; private int TransferFileType; Boolean privé RenameUplowed; private int rerytimes; public String gethost () {return host; } public void sethost (string host) {this. host = host; } public int getport () {port de retour; } public void setport (int port) {this. port = port; } public String getUserName () {return username; } public void setUsername (String Username) {this. nom d'utilisateur = nom d'utilisateur; } public String getPassword () {return mot de passe; } public void setPassword (String Motword) {this. mot de passe = mot de passe; } public String getPassiveMode () {return passiveMode; } public void setPassiveMode (String PassiveMode) {this. PASSIVEMODE = PASSIVEMODE; } public String getEncoding () {return Encoding; } public void setEncoding (String Encoding) {this. codage = codage; } public int GetClientTimeout () {return clientTimeout; } public void setClientTimeout (int clientTimeout) {this. clientTimeOut = clientTimeOut; } public int getThreadnum () {return threadnum; } public void setThreadnum (int threadnum) {this. Threadnum = threadnum; } public int getTransferFileType () {return transferfileType; } public void setTransferFileType (int TransferFileType) {this. transfertFileType = transferFileType; } public boolean isReNameUploaded () {return renameuplowed; } public void setReNameUploaded (boolean renameuplowed) {this. RenameUploaded = RenameUpLoDed; } public int getRetryTimes () {return reryTimes; } public void SetTretryTimes (int rerytimes) {ceci. rerytimes = rerytimes; } @Override public String toString () {return "ftpClientConfig [host =" + host + "/ n port =" + port + "/ n username =" + username + "/ n mot de passe =" + mot de passe + "/ n passiveMode =" + passiveMode + "/ n Encoding =" + Encoding + "/ n clientTimeout =" + clientout + " "/ n transfertFileType =" + transferfileType + "/ n renameUploaded =" + renameuploaded + "/ n rerytimes =" + retRyTimes + "]"; }}La classe de pool de connexion FTPClientPool gère le cycle de vie de l'objet FTPClient et est responsable des prêts, de la planification et de la destruction de la piscine. La classe FTPClientPool dépend de la classe FTPClientFactory, qui est utilisée pour créer et détruire des objets par cette classe d'ingénierie; Le FTPClientFactory repose également sur la classe FTPClientConfigure, qui est responsable de l'encapsulation des paramètres de configuration du FTPClient. À ce stade, notre pool de connexions FTPClient a été développé.
Il convient de noter qu'un ArrayBlockingQueue est utilisé dans FTPClientPool pour gérer et stocker des objets FTPClient. Pour bloquer les files d'attente, veuillez vous référer à mon article: [concurrence Java] BlockingQueue
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.