Recentemente, estou escrevendo uma ferramenta de upload FTP e usando o FTPClient da Apache. Para melhorar a eficiência do upload, adotei uma abordagem multithread, mas a criação e a destruição frequentes de objetos FTPClient por cada encadeamento causarão inevitavelmente sobrecarga desnecessária. Portanto, é melhor usar um pool de conexão FTPClient aqui. Eu olhei cuidadosamente através da API Apache e descobri que ela não tinha uma implementação do FTPClientPool, então tive que escrever um FTPClientPool. O seguinte apresentará todo o processo de desenvolvimento de um pool de conexões para sua referência.
Sobre pool de objetos
Alguns objetos têm uma sobrecarga relativamente alta, como conexões de banco de dados. Para reduzir o consumo de desempenho causado pela criação e destruição frequente de objetos, podemos usar a tecnologia do pool de objetos para obter a reutilização de objetos. O Pool de Objetos fornece um mecanismo que pode gerenciar o ciclo de vida dos objetos no pool de objetos, fornece um método para obter e liberar objetos e permite que os clientes usem facilmente objetos no pool de objetos.
Se queremos implementar um pool de objetos, geralmente precisamos concluir as seguintes funções:
1. Se houver objetos disponíveis no pool, o pool de objetos poderá retornar ao cliente.
2. Depois que o cliente coloca os objetos de volta na piscina, eles podem reutilizá -los.
3. Os pools de objetos podem criar novos objetos para atender às crescentes necessidades dos clientes
4. Existe um mecanismo para fechar adequadamente a piscina para encerrar o ciclo de vida do objeto
Kit de ferramentas do pool de objetos do Apache
Para facilitar o desenvolvimento de nosso próprio pool de objetos, o kit de ferramentas com comum fornecido pelo Apache contém algumas interfaces e classes de implementação para o desenvolvimento de pools de objetos comuns. As duas interfaces mais básicas são ObjectPool e PoolableObjectFactory.
Existem vários métodos básicos na interface ObjectPool:
1. AddObject (): adicione objeto ao pool
2. BorrowObject (): o cliente empresta um objeto da piscina
3. returnObject (): o cliente retorna um objeto para o pool
4. Fechar (): Feche o pool de objetos, limpe a memória e os recursos de liberação, etc.
5. SetFactory (ObjectFactory Factory): é necessária uma fábrica para criar objetos no pool.
Vários métodos básicos na interface PoolableObjectFactory:
1. MakeObject (): faça um objeto
2. DestoryObject (): Destrua um objeto
3. ValideBject (): Verifique se um objeto ainda está disponível
Através das duas interfaces acima, podemos implementar um pool de objetos por nós mesmos.
Exemplo: desenvolva um pool de objetos FTPClient
Recentemente, está sendo desenvolvido um projeto que requer o upload de arquivos no HDFS para um grupo de servidores FTP. Para melhorar a eficiência do upload, consideramos naturalmente o uso de métodos multithread para fazer o upload. A ferramenta que carreguei FTP é o FTPClient no pacote Common-Net Apache, mas o Apache não fornece FTPClientPool. Portanto, para reduzir o número de vezes que o FTPClient é criado e destruído, desenvolvemos um FTPClientPool para reutilizar a conexão FTPClient.
Através da introdução acima, podemos usar o pacote comum fornecido pelo Apache para nos ajudar a desenvolver pools de conexão. Para desenvolver um pool de objetos simples, você só precisa implementar as interfaces ObjectPool e PoolableObjectFactory no pacote comum. Vamos dar uma olhada na implementação que escrevi:
Escreva uma implementação de interface ObjectPool ftpclientpool
import java.io.IOException;import java.util.NoSuchElementException;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;import java.util.concurrent.TimeUnit;import org.apache.commons.net.ftp.FTPClient;import org.apache.commons.pool.objectpool; importar org.apache.commons.pool.poolableObjectFactory;/*** Implemente um pool de conexão FTPClient*@Author Heaven*/public class FTPCLIENTPOOL implementa ObjectPool <FTPPLIENT> {private final int default_Pool_s BlockingQueue final privado <FTPClient> Pool; Fábrica final privada FTPClientFactory; / ** * Inicializando o pool de conexão, uma fábrica precisa ser injetada para fornecer a instância ftpClient * @param fábrica * @throws Exceção */ public ftpClientPool (ftpClientFactory Factory) lança exceção {this (default_pool_size, fábrica); } / ** * * @param maxpoolsize * @param factory * @throws Exception * / public ftpClientPool (int poolsize, ftpClientFactory Factory) lança exceção {this.factory = factory; Pool = novo ArrayBlockingQueue <FtpClient> (PoolSize*2); initpool (PoolSize); } /** * Inicializando o pool de conexões, uma fábrica precisa ser injetada para fornecer a instância ftpclient * @param maxpoolsize * @throws exceção * /private void initpool (int maxpoolsize) lança exceção {para (int i = 0; i <maxpoolsize; i ++) {/// // addob para (int i = 0; i <maxpoolsize; i ++) {/ }} / * (não-javadoc) * @see org.apache.commons.pool.objectpool#borrowobject () * / public ftpClient borthobject () lança exceção, noschelementException, ilegalstateException {ftpclient client = pool.take (); if (client == null) {client = factory.makeObject (); addObject (); } else if (! factory.validateBject (client)) {// verifique se não passa // faça o objeto InvalidateBject (cliente); // Faça e adicione novos objetos ao pool cliente = Factory.makeObject (); addObject (); } retornar cliente; } / * (não javadoc) * @see org.apache.commons.pool.objectpool#returnObject (java.lang.object) * / public void returnObject (ftpclient client) lança exceção {if ((client! = nul) &&! } catch (ioexception e) {e.printStackTrace (); }}} public void InvalidateBject (cliente ftpClient) lança a exceção {// remove o cliente invalidado pool.remove (cliente); } / * (não javadoc) * @see org.apache.commons.pool.objectpool#addObject () * /public void addObject () lança exceção, ilegalStateException, não suportada); } public int getNumidle () lança UnsupportEdOperationException {return 0; } public int getNumactive () lança UnsupportEdOperationException {return 0; } public void clear () lança exceção, unsupportEdOperationException {} / * (não javadoc) * @see org.apache.commons.pool.objectpool#close () * / public void Close () lança exceção {while (pool.iterator (). Factory.DestroyObject (Client); }} public void setFactory (PoolableObjectFactory <FTPClient> fábrica) lança ilegalStateException, UnsupportEdOperationException {}}Escreva outra implementação da interface PoolableObjectFactory FTPClientFactory
importar java.io.ioException; importar org.apache.commons.net.ftp.ftpclient; importar org.apache.commons.net.ftp.ftpreply; importar org.apache.commons.pool.poolableBjectFactory; importação org.lf4j.portgger; importação ouslf oug.slf; com.hdfstoftp.util.ftpclientException;/*** FtpClient Factory Class, fornece a criação e destruição de instâncias de FTPClient através da fábrica ftpClient*@author Heaven*/public class Logger Logger Logger Logger Config privado ftpClientConfigure; // Pausa um objeto de parâmetro para a fábrica para facilitar a configuração dos parâmetros relevantes do FTPClient FTPClientFactory (ftpClientConfigure config) {this.config = config; } / * (não javadoc) * @see org.apache.commons.pool.poolableObjectFactory#makeObject () * / public ftpClient makeObject () lança exceção {ftpClient ftpcient = new ftpClient (); ftpClient.SetConnectTimeout (config.getClientTimeout ()); tente {ftpclient.connect (config.gethost (), config.getport ()); int reply = ftpClient.getReplyCode (); if (! ftpreply.ispositiveciction (resposta)) {ftpclient.disconnect (); Logger.warn ("FTPServer Recused Connection"); retornar nulo; } resultado booleano = ftpClient.login (config.getUserName (), config.getpassword ()); if (! Result) {lança novo ftpClientException ("Falha de login ftpClient! } 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 (); } retornar ftpClient; } / * (não javadoc) * @see org.apache.commons.pool.poolableObjectFactory#DestroyObject (java.lang.Object) * / public void DestroyObject (ftpClient ftpclient) lança excepção {Try {if (ftp) }} catch (ioexception io) {io.printStackTrace (); } finalmente {// observe que você deve desconectar a conexão no código finalmente, caso contrário, ela fará com que a conexão FTP seja ocupada, tente {ftpclient.disconnect (); } catch (ioexception io) {io.printStackTrace (); }}} / * (não javadoc) * @see org.apache.commons.pool.poolableObjectFactory#validateBject (java.lang.Object) * / public boolean validoBject (ftpclient ftpclient) {try {retorn ftppClient.sendnoop (); } catch (ioexception e) {lança a nova run timeException ("Falha ao validar o cliente:" + e, e); }} public void ActivateObject (ftpClient ftpClient) lança Exceção {} public void passivateObject (ftpClient ftpClient) lança exceção {}}Finalmente, é melhor passar um objeto de parâmetro para a fábrica para facilitar a definição de alguns parâmetros de ftpclient
pacote org.apache.commons.pool.impl.contrib;/** * FTPCLIENT Configuration Class, encapsula a configuração relevante do ftpClient * * @Author Heaven */public class FtpClientConfigure {Private String host; private int porta; Nome de usuário privado de string; senha de sequência privada; String private Passivemode; codificação de string privada; private int clienttimeout; private int threadnum; private int transferfileType; Renomear booleano privado; privado int repetirtimes; public string gethost () {return host; } public void sethost (host de string) {this. host = host; } public int getport () {return porta; } public void Setport (int porta) {this. porta = porta; } public string getUserName () {return userName; } public void setUserName (String UserName) {this. nome de usuário = nome de usuário; } public string getPassword () {return senha; } public void setPassword (senha da string) {this. senha = senha; } public string getPassivEMode () {return passiveMode; } public void SetPassivEmode (String passiveMode) {this. passiveMode = passiveMode; } public string getEncoding () {return coding; } public void setencoding (codificação de string) {this. codificação = codificação; } 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. transferfileType = transferfileType; } public boolean IsrenameUploaded () {return renameUploaded; } public void setrenameUpload (boolean renomeouPloaded) {this. renomeuPloaded = renomeuPloaded; } public int getRretryTimes () {return reprerytimes; } public void SetretRyTimes (int RetryTimes) {this. REPRYTIMENTES = RETRYTIMES; } @Override public String tostring () {return "ftpclientConfig [host =" + host + "/n porta =" + porta + "/n userName =" + nome de usuário + "/n senha =" + senha + "/n passivemode =" + passivode + "/n benging =" + encobingout + "/n clientout/n clientout/n clientout/n clientout +" + "/n. "/n transferfileType =" + transferfileType + "/n renameUploaded =" + renameUploaded + "/n retrytimes =" + retrytimes + "]"; }}A classe do pool de conexão FTPClientPool gerencia o ciclo de vida do objeto FTPClient e é responsável pelos empréstimos, planejamento e destruição da piscina. A classe FTPClientPool depende da classe FTPClientFactory, usada para criar e destruir objetos por essa classe de engenharia; O FTPClientFactory também se baseia na classe FTPClientConfigure, responsável por encapsular os parâmetros de configuração do FTPClient. Neste ponto, nosso pool de conexão FTPClient foi desenvolvido.
Deve -se notar que um quadro de matriz é usado no FTPClientPool para gerenciar e armazenar objetos FTPClient. Para bloquear filas, consulte o meu artigo: [Java Concurrency] BlockingQueue
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.