一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java FTPClient連接池的實現

Java FTPClient連接池的實現

2021-05-11 14:02Heaven-Wang Java教程

這篇文章主要介紹了Java FTPClient連接池的實現,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

最近在寫一個ftp上傳工具,用到了apache的ftpclient,為了提高上傳效率,我采用了多線程的方式,但是每個線程頻繁的創建和銷毀ftpclient對象勢必會造成不必要的開銷,因此,此處最好使用一個ftpclient連接池。仔細翻了一下apache的api,發現它并沒有一個ftpclientpool的實現,所以,不得不自己寫一個ftpclientpool。下面就大體介紹一下開發連接池的整個過程,供大家參考。

關于對象池

有些對象的創建開銷是比較大的,比如數據庫連接等。為了減少頻繁創建、銷毀對象帶來的性能消耗,我們可以利用對象池的技術來實現對象的復用。對象池提供了一種機制,它可以管理對象池中對象的生命周期,提供了獲取和釋放對象的方法,可以讓客戶端很方便的使用對象池中的對象。

如果我們要自己實現一個對象池,一般需要完成如下功能:

1. 如果池中有可用的對象,對象池應當能返回給客戶端
2. 客戶端把對象放回池里后,可以對這些對象進行重用
3. 對象池能夠創建新的對象來滿足客戶端不斷增長的需求
4. 需要有一個正確關閉池的機制來結束對象的生命周期

apache的對象池工具包

為了方便我們開發自己的對象池,apache 提供的common-pool工具包,里面包含了開發通用對象池的一些接口和實現類。其中最基本的兩個接口是objectpool 和poolableobjectfactory。

objectpool接口中有幾個最基本的方法:

1. addobject() : 添加對象到池
2. borrowobject():客戶端從池中借出一個對象
3. returnobject():客戶端歸還一個對象到池中
4. close():關閉對象池,清理內存釋放資源等
5. setfactory(objectfactory factory):需要一個工廠來制造池中的對象

poolableobjectfactory接口中幾個最基本的方法:

1. makeobject():制造一個對象
2. destoryobject():銷毀一個對象
3. validateobject():驗證一個對象是否還可用

通過以上兩個接口我們就可以自己實現一個對象池了。

實例:開發一個ftpclient對象池

最近在開發一個項目,需要把hdfs中的文件上傳到一組ftp服務器,為了提高上傳效率,自然考慮到使用多線程的方式進行上傳。我上傳ftp用的工具是apache common-net包中的ftpclient,但apache并沒有提供ftpclientpool,于是為了減少ftpclient的創建銷毀次數,我們就自己開發一個ftpclientpool來復用ftpclient連接。

通過上面的介紹,我們可以利用apache提供的common-pool包來協助我們開發連接池。而開發一個簡單的對象池,僅需要實現common-pool 包中的objectpool和poolableobjectfactory兩個接口即可。下面就看一下我寫的實現:

寫一個objectpool接口的實現ftpclientpool

?
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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;
import org.apache.commons.pool.poolableobjectfactory;
 
/**
* 實現了一個ftpclient連接池
* @author heaven
*/
public class ftpclientpool implements objectpool<ftpclient>{
 private static final int default_pool_size = 10;
 private final blockingqueue<ftpclient> pool;
 private final ftpclientfactory factory;
 
 /**
 * 初始化連接池,需要注入一個工廠來提供ftpclient實例
 * @param factory
 * @throws exception
 */
 public ftpclientpool(ftpclientfactory factory) throws exception{
   this(default_pool_size, factory);
 }
 /**
 *
 * @param maxpoolsize
 * @param factory
 * @throws exception
 */
 public ftpclientpool(int poolsize, ftpclientfactory factory) throws exception {
   this.factory = factory;
   pool = new arrayblockingqueue<ftpclient>(poolsize*2);
   initpool(poolsize);
 }
 /**
 * 初始化連接池,需要注入一個工廠來提供ftpclient實例
 * @param maxpoolsize
 * @throws exception
 */
 private void initpool(int maxpoolsize) throws exception {
   for(int i=0;i<maxpoolsize;i++){
      //往池中添加對象
      addobject();
   }
 
 }
 /* (non-javadoc)
 * @see org.apache.commons.pool.objectpool#borrowobject()
 */
 public ftpclient borrowobject() throws exception, nosuchelementexception, illegalstateexception {
   ftpclient client = pool.take();
   if (client == null) {
      client = factory.makeobject();
      addobject();
   }else if(!factory.validateobject(client)){//驗證不通過
      //使對象在池中失效
      invalidateobject(client);
      //制造并添加新對象到池中
      client = factory.makeobject();
      addobject();
   }
   return client;
 
 }
 
 /* (non-javadoc)
 * @see org.apache.commons.pool.objectpool#returnobject(java.lang.object)
 */
 public void returnobject(ftpclient client) throws exception {
   if ((client != null) && !pool.offer(client,3,timeunit.seconds)) {
      try {
        factory.destroyobject(client);
      } catch (ioexception e) {
        e.printstacktrace();
      }
   }
 }
 
 public void invalidateobject(ftpclient client) throws exception {
   //移除無效的客戶端
   pool.remove(client);
 }
 
 /* (non-javadoc)
 * @see org.apache.commons.pool.objectpool#addobject()
 */
 public void addobject() throws exception, illegalstateexception, unsupportedoperationexception {
   //插入對象到隊列
   pool.offer(factory.makeobject(),3,timeunit.seconds);
 }
 
 public int getnumidle() throws unsupportedoperationexception {
   return 0;
 }
 
 public int getnumactive() throws unsupportedoperationexception {
   return 0;
 }
 
 public void clear() throws exception, unsupportedoperationexception {
 
 }
 
 /* (non-javadoc)
 * @see org.apache.commons.pool.objectpool#close()
 */
 public void close() throws exception {
   while(pool.iterator().hasnext()){
      ftpclient client = pool.take();
      factory.destroyobject(client);
   }
 }
 
 public void setfactory(poolableobjectfactory<ftpclient> factory) throws illegalstateexception, unsupportedoperationexception {
 
 }
}

再寫一個poolableobjectfactory接口的實現ftpclientfactory

?
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import java.io.ioexception;
import org.apache.commons.net.ftp.ftpclient;
import org.apache.commons.net.ftp.ftpreply;
import org.apache.commons.pool.poolableobjectfactory;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
 
import com.hdfstoftp.util.ftpclientexception;
 
/**
* ftpclient工廠類,通過ftpclient工廠提供ftpclient實例的創建和銷毀
* @author heaven
*/
public class ftpclientfactory implements poolableobjectfactory<ftpclient> {
private static logger logger = loggerfactory.getlogger("file");
 private ftpclientconfigure config;
 //給工廠傳入一個參數對象,方便配置ftpclient的相關參數
 public ftpclientfactory(ftpclientconfigure config){
   this.config=config;
 }
 
 /* (non-javadoc)
 * @see org.apache.commons.pool.poolableobjectfactory#makeobject()
 */
 public ftpclient makeobject() throws exception {
   ftpclient ftpclient = new ftpclient();
   ftpclient.setconnecttimeout(config.getclienttimeout());
   try {
      ftpclient.connect(config.gethost(), config.getport());
      int reply = ftpclient.getreplycode();
      if (!ftpreply.ispositivecompletion(reply)) {
        ftpclient.disconnect();
        logger.warn("ftpserver refused connection");
        return null;
      }
      boolean result = ftpclient.login(config.getusername(), config.getpassword());
      if (!result) {
        throw new ftpclientexception("ftpclient登陸失敗! username:" + config.getusername() + " ; password:" + 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;
 }
 
 /* (non-javadoc)
 * @see org.apache.commons.pool.poolableobjectfactory#destroyobject(java.lang.object)
 */
 public void destroyobject(ftpclient ftpclient) throws exception {
   try {
      if (ftpclient != null && ftpclient.isconnected()) {
        ftpclient.logout();
      }
   } catch (ioexception io) {
      io.printstacktrace();
   } finally {
      // 注意,一定要在finally代碼中斷開連接,否則會導致占用ftp連接情況
      try {
        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) {
      throw new runtimeexception("failed to validate client: " + e, e);
   }
 }
 
 public void activateobject(ftpclient ftpclient) throws exception {
 }
 
 public void passivateobject(ftpclient ftpclient) throws exception {
 
 }
}

最后,我們最好給工廠傳遞一個參數對象,方便我們設置ftpclient的一些參數

?
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package org.apache.commons.pool.impl.contrib;
 
/**
 * ftpclient配置類,封裝了ftpclient的相關配置
 *
 * @author heaven
 */
public class ftpclientconfigure {
 private string host;
 private int port;
 private string username;
 private string password;
 private string passivemode;
 private string encoding;
 private int clienttimeout;
 private int threadnum;
 private int transferfiletype;
 private boolean renameuploaded;
 private int retrytimes;
 
 public string gethost() {
     return host;
 }
 
 public void sethost(string host) {
     this. host = host;
 }
 
 public int getport() {
     return port;
 }
 
 public void setport(int port) {
     this. port = port;
 }
 
 public string getusername() {
     return username;
 }
 
 public void setusername(string username) {
     this. username = username;
 }
 
 public string getpassword() {
     return password;
 }
 
 public void setpassword(string password) {
     this. password = password;
 }
 
 
 public string getpassivemode() {
     return passivemode;
 }
 
 public void setpassivemode(string passivemode) {
     this. passivemode = passivemode;
 }
 
 public string getencoding() {
     return encoding;
 }
 
 public void setencoding(string encoding) {
     this. encoding = encoding;
 }
 
 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 setrenameuploaded( boolean renameuploaded) {
     this. renameuploaded = renameuploaded;
 }
 
 public int getretrytimes() {
     return retrytimes;
 }
 
 public void setretrytimes( int retrytimes) {
     this. retrytimes = retrytimes;
 }
 
 @override
 public string tostring() {
     return "ftpclientconfig [host=" + host + "\n port=" + port + "\n username=" + username + "\n password=" + password  + "\n passivemode=" + passivemode
          + "\n encoding=" + encoding + "\n clienttimeout=" + clienttimeout + "\n threadnum=" + threadnum + "\n transferfiletype="
          + transferfiletype + "\n renameuploaded=" + renameuploaded + "\n retrytimes=" + retrytimes + "]" ;
 }
 
}

 ftpclientpool連接池類管理ftpclient對象的生命周期,負責對象的借出、規劃、池的銷毀等;ftpclientpool類依賴于ftpclientfactory類,由這個工程類來制造和銷毀對象;ftpclientfactory又依賴ftpclientconfigure類,ftpclientconfigure負責封裝ftpclient的配置參數。至此,我們的ftpclient連接池就開發完成了。

需要注意的是,ftpclientpool中用到了一個阻塞隊列arrayblockingqueue來管理存放ftpclient對象,關于阻塞隊列,請參考我的這篇文章: 【java并發之】blockingqueue

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/suifeng3051/article/details/48969679

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成年美女黄网色大观看全 | 亚洲欧美一区二区三区在线观看 | 国产欧美一区二区精品久久久 | 动漫美女被吸乳 | 97爱干 | 国产在线视频第一页 | 天干夜天天夜天干天ww | 成人免费草草视频 | 国产亚洲人成网站天堂岛 | 九九精品国产亚洲A片无码 九九99热久久999精品 | 国产精品www视频免费看 | 国产xxxxxx久色视频在 | 国产精品久久久久久网站 | 大又大又粗又爽女人毛片 | 亚洲成人影院在线观看 | 肉肉小说在线阅读 | 石原莉奈被店长侵犯免费 | 忘忧草在线社区WWW日本-韩国 | 国产裸舞在线一区二区 | 国产欧美成人免费观看 | 国产首页精品 | av91在线| 亚洲天天综合 | 操老妇| 毛片在线播放a | 午夜在线观看视频 | 亚洲精品第二页 | 欧美激烈精交gif动态图18p | 国产nv精品你懂得 | 色综合中文字幕在线亚洲 | 日本中文字幕在线视频站 | 男人天堂2023 | 日本福利视频一区 | 色依依视频视频在线观看 | 1024毛片| 亚洲AV精品无码喷水直播间 | 夫妻性生活在线 | 日不卡 | 日本高清视频网站 | 欧美一级片在线看 | 欧美一区二区三区成人看不卡 |