Recientemente, estoy escribiendo una herramienta de carga FTP y uso FTPClient de Apache. Para mejorar la eficiencia de carga, he adoptado un enfoque multiproceso, pero la creación y destrucción frecuente de objetos de FTPClient por cada hilo inevitablemente causará una sobrecarga innecesaria. Por lo tanto, es mejor usar un grupo de conexión FTPClient aquí. Miré cuidadosamente a través de la API de Apache y descubrí que no tenía una implementación de FTPClientPool, por lo que tuve que escribir un FTPClientPool yo mismo. Lo siguiente introducirá todo el proceso de desarrollo de un grupo de conexión para su referencia.
Sobre la piscina de objetos
Algunos objetos tienen una sobrecarga relativamente alta, como las conexiones de la base de datos. Para reducir el consumo de rendimiento causado por la creación frecuente y la destrucción de los objetos, podemos usar la tecnología de la agrupación de objetos para lograr la reutilización de objetos. El grupo de objetos proporciona un mecanismo que puede administrar el ciclo de vida de los objetos en el grupo de objetos, proporciona un método para obtener y liberar objetos, y permite a los clientes usar fácilmente objetos en el grupo de objetos.
Si queremos implementar un grupo de objetos nosotros mismos, generalmente necesitamos completar las siguientes funciones:
1. Si hay objetos disponibles en la piscina, el grupo de objetos debería poder volver al cliente.
2. Después de que el cliente vuelva a colocar los objetos en la piscina, pueden reutilizarlos.
3. Los grupos de objetos pueden crear nuevos objetos para satisfacer las crecientes necesidades de los clientes
4. Hay un mecanismo para cerrar adecuadamente la piscina para terminar el ciclo de vida del objeto
Kit de herramientas de grupo de objetos de Apache
Para facilitarnos que desarrollemos nuestro propio grupo de objetos, el kit de herramientas de putos comunes proporcionado por Apache contiene algunas interfaces y clases de implementación para desarrollar grupos de objetos comunes. Las dos interfaces más básicas son Objectpool y PoolableObjectFactory.
Existen varios métodos básicos en la interfaz ObjectPool:
1. AddObject (): Agregue objeto a la piscina
2. LibritoBject (): el cliente toma un objeto de la piscina
3. ReturnObject (): el cliente devuelve un objeto al grupo
4. Cerrar (): Cierre el grupo de objetos, la memoria limpia y la liberación de recursos, etc.
5. SetFactory (ObjectFactory Factory): se necesita una fábrica para crear objetos en el grupo.
Varios métodos básicos en la interfaz PoolableObjectFactory:
1. MakeObject (): hacer un objeto
2. DestoryObject (): destruye un objeto
3. ValidateObject (): Verifique si todavía hay un objeto disponible
A través de las dos interfaces anteriores, podemos implementar un grupo de objetos por nosotros mismos.
Ejemplo: desarrolle un grupo de objetos ftpclient
Recientemente, se está desarrollando un proyecto que requiere cargar archivos en HDFS a un grupo de servidores FTP. Para mejorar la eficiencia de carga, naturalmente consideramos usar métodos de subprocesos múltiples para cargar. La herramienta que cargué FTP es el FTPClient en el paquete Apache Common-Net, pero Apache no proporciona FTPClientPool. Entonces, para reducir la cantidad de veces que se crea y destruye el FTPClient, desarrollamos un FTPClientPool nosotros mismos para reutilizar la conexión FTPClient.
A través de la introducción anterior, podemos usar el paquete de putos comunes proporcionado por Apache para ayudarnos a desarrollar grupos de conexión. Para desarrollar un grupo de objetos simple, solo necesita implementar las interfaces ObjectPool y PoolableObjectFactory en el paquete Common-Pool. Echemos un vistazo a la implementación que escribí:
Escriba una implementación de interfaz de ObjectPool ftpClientPool
import java.io.ioException; import java.util.nosuchelementException; import java.util.concurrent.arrayBlockqueue; import java.util.concurrent.blockingqueue; import java.util.concurrent.timeunit; import og.apache.commons.ftp.ftpclient; import; importar; import org.apache.commons.pool.objectpool; import org.apache.commons.pool.poolableBjectFactory;/*** Implemente un grupo de conexión ftpClient*@author heavy*/public class ftpClientPool implementa objeto de objetos <ftpclient> {private estatic final int outhorT_pool_size = 10; Bloqueo final privado <ftpclient> piscina; Factory FTPClientFactory final privada; / ** * Inicializando el grupo de conexión, se debe inyectar una fábrica para proporcionar la instancia de ftpClient * @param factory * @throws excepción */ public ftpClientPool (ftpClientFactory factory) arroja excepción {this (default_pool_size, factory); } / ** * * @param maxpoolsize * @param factory * @throws excepción * / public ftpClientPool (int PoolSize, ftpClientFactory factory) lanza la excepción {this.Factory = factory; Pool = new ArrayBlockingqueue <FtpClient> (PoolSize*2); initpool (PoolSize); } /** * Inicializando el grupo de conexión, se debe inyectar una fábrica para proporcionar la instancia ftpclient * @param maxpoolSize * @throws excepción * /private void initpool (int maxpoolSize) lanza la excepción {for (int i = 0; i <maxpoolSize; i ++) {// add ojus to the Pool addObject ();); }} / * (no javadoc) * @see org.apache.commons.pool.Objectpool#libritoBject () * / public ftpClient LiborwObject () arroja excepción, nosuchelementException, ilegalStateException {ftpClient Client = Pool.take (); if (client == null) {client = factory.makeObject (); addObject (); } else if (! factory.validateObject (cliente)) {// Verifique no pasar // hacer que el objeto invalidateObject (cliente); // hacer y agregar nuevos objetos al cliente de piscina = factory.makeObject (); addObject (); } Return Client; } / * (no javadoc) * @see org.apache.commons.pool.objectpool#returnObject (java.lang.object) * / public void returnObject (ftpClient Client) lanza la excepción {if ((cliente! = null) &&! Pool.offer (Client, 3, TimeUnit.Seconds)) {Try {factory.datjer } catch (ioException e) {E.PrintStackTrace (); }}} public void InvalidateObject (cliente ftpClient) lanza la excepción {// Eliminar invalidar clientes piscina.remove (cliente); } / * (no javadoc) * @see org.apache.commons.pool.objectpool#addObject () * /public void addObject () lanza excepción, ilegalStateException, no comportedOperationException {// inserta el objeto a la piscina de cola. } public int getNumidle () lanza no compatible } public int getNumactive () lanza no compatible } public void clare () lanza la excepción, UnsupportedOperationException {} / * (no javadoc) * @see org.apache.commons.pool.objectpool#cerrador () * / public void Close () Exception {while (piscol.iterator (). Hasnext ()) {ftpClient CLIENT = Pool.take (); factory.destroyObject (cliente); }} public void setFactory (PoolableObjectFactory <ftpClient> fábrica) arroja ilegalStateException, no apoyo a la operación {}}Escriba otra implementación de interfaz de FuncionableFactory ftpClientFactory
import java.io.ioException; import org.apache.commons.net.ftp.ftpclient; import org.apache.commons.net.ftp.ftpreply; import org.apache.commons.pool.poolableBjectFactory; import og.slf4j.logger; importar org.slf4j.loggerfactory; import; importar; importar; importar org.sslf4j.logger; com.hdfstoftp.util.ftpClientException;/*** FtpClient Class de fábrica, proporciona la creación y destrucción de las instancias de ftpClient a través de la fábrica ftpclient*@author heavy*/public class ftpClientFactory Implements PoolableFactory <ftpClient> {logger estatic de logger = loggerfactory.getLogger (""); ""); configuración privada ftpClientConfigure; // Pausa un objeto de parámetro a la fábrica para facilitar la configuración de los parámetros relevantes de ftpClient public ftpClientFactory (ftpClientConfigure config) {this.config = config; } / * (no javadoc) * @see org.apache.commons.pool.poolableObjectFactory#makeObject () * / public ftpClient MakeObject () lanza excepción {ftpClient ftpClient = new ftpClient (); ftpClient.SetConnectTimeOut (config.getClientTimeOut ()); Pruebe {ftpclient.connect (config.gethost (), config.getport ()); int respuesta = ftpclient.getReplyCode (); if (! ftPreply.ispositiveCompletion (respuesta)) {ftpClient.Disconnect (); logger.warn ("conexión ftpserver rechazada"); regresar nulo; } resultado boolean = ftpclient.login (config.getUsername (), config.getPassword ()); if (! resultado) {tire nuevo ftpClientException ("ftpClient Login falló! Nombre de usuario:" + config.getUsername () + "; contraseña:" + config.getPassword ()); } ftpclient.setFileType (config.getTransferFileType ()); ftpClient.SetBufferSize (1024); ftpclient.setControlEncoding (config.getEncoding ()); if (config.getPassIvEmode (). Equals ("true")) {ftpClient.EnterLocalPassIvemode (); }} catch (ioException e) {E.PrintStackTrace (); } catch (ftpClientException e) {E.PrintStackTrace (); } return ftpClient; } / * (no javadoc) * @see org.apache.commons.pool.poolableObjectFactory#destruyeBject (java.lang.object) * / public void destruyoBject (ftpClient ftpClient) lanza la excepción {try {if (ftpClient! = null && ftpClient.Isconnectect ())) }} Catch (ioException io) {io.printstacktrace (); } Finalmente {// Tenga en cuenta que debe desconectar la conexión en el código finalmente; de lo contrario, hará que la conexión FTP esté ocupada, intente {ftpClient.disconnect (); } catch (ioException io) {io.printstackTrace (); }}} / * (no javadoc) * @see org.apache.commons.pool.poolableBjectFactory#validateObject (java.lang.object) * / public boolean validateObject (ftpClient ftpClient) {try {return ftpClient.sendnoop (); } Catch (ioException e) {Throw New RuntimeException ("Error al validar el cliente:" + E, E); }} public void activateObject (ftpClient ftpClient) lanza la excepción {} public void passivateObject (ftpClient ftpClient) lanza la excepción {}}Finalmente, es mejor pasar un objeto de parámetro a la fábrica para facilitarnos establecer algunos parámetros de FTPClient
paquete org.apache.commons.pool.impl.contrib;/** * clase de configuración ftpclient, encapsula la configuración relevante de ftpclient * * @author heavy */public class ftpClientConfigure {host de cadena privada; Puerto privado int; nombre de usuario de cadena privada; contraseña de cadena privada; cadena privada passivemode; codificación de cadena privada; Private int ClientTimeOut; privado int threadnum; Private int TransferFileType; Private Boolean renombrado privado int retrytimes; public String gethost () {return host; } public void sethost (host de cadena) {this. host = host; } public int getPort () {return Port; } public void setport (int puerto) {this. puerto = puerto; } public String getUsername () {return UserName; } public void setUsername (String UserName) {this. nombre de usuario = nombre de usuario; } public String getPassword () {return Password; } public void setPassword (contraseña de cadena) {esto. contraseña = contraseña; } public String getPassivemode () {return passiveMode; } public void setPassivemode (string passiveMode) {this. passiveMode = passiveMode; } public String getEncoding () {return coding; } public void setEncoding (codificación de cadena) {this. codificación = codificación; } 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) {esto. transferFileType = TransferFileType; } public boolean isrenameuploaded () {return renameuploaded; } public void setRenameUploaded (boolean renameuploaded) {this. renameUPLOADED = renameuploaded; } public int getcretryTimes () {return retryTimes; } public void setretryTimes (int retryTimes) {this. retrytimes = retryTimes; } @Override public String toString () {return "ftpClientConfig [host =" + host + "/n Port =" + puerto + "/n username =" + username + "/n contraseña =" + contraseña + "/n passivemode =" + passivemode + "/n encoding =" + encoding/"n clienteutmiout =" + clienttimeut + "n. "/n transferfileType =" + transferfileType + "/n renombreaded =" + renameuploaded + "/n retryTimes =" + retryTimes + "]"; }}La clase FTPClientPool Connection Pool gestiona el ciclo de vida del objeto FTPClient, y es responsable de los préstamos, planificación y destrucción de la piscina. La clase FTPClientPool depende de la clase FTPClientFactory, que se utiliza para crear y destruir objetos mediante esta clase de ingeniería; FTPClientFactory también se basa en la clase FTPClientConfigure, que es responsable de encapsular los parámetros de configuración del FTPClient. En este punto, se ha desarrollado nuestro grupo de conexión FTPClient.
Cabe señalar que se utiliza una matriz de matriz en FTPClientPool para administrar y almacenar objetos FTPClient. Para las colas de bloqueo, consulte mi artículo: [Java Concurrencia] Bloquequequeue
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.