Java – Socket串連池

來源:互聯網
上載者:User

1:SocketAdapter類,此類繼承了socket,重載了socket類的close方法,目的是當使用者關閉socket的時候,我們並不關閉它只是放在串連池內部。
package com.tarena.socketpool;
import java.net.*;
import java.io.IOException;
/**
* <p>socket串連的簡單實現</p>
* <p>Description: </p>
* <p>Copyright: Copyright Tarena(c) 2005</p>
* <p>Company: Tarena</p>
* @author chengxing
* @version 1.0
*/
public class ConnectionAdapter extends  Socket{
  /**
   * 串連狀態
   */
  private boolean status=true;
  /**
   * 預設的建構函式
   */
  public ConnectionAdapter() {
    super();
  }
  public ConnectionAdapter(String host,int port)throws UnknownHostException,IOException{
    super(host,port);
  }
  /**
   * 判斷此串連是否空閑
   * @return boolean 空閑返回ture,否則false
   */
  public boolean isFree(){
    return status;
  }
  /**
   * 當使用此串連的時候設定狀態為false(忙碌)
   */
  public void setBusy(){
    this.status=false;
  }
  /**
   * 當用戶端關閉串連的時候狀態設定為true(空閑)
   */
  public void close(){
    System.out.println(Close : set the status is free );
    status=true;
  }
  public void destroy(){
    //Close socket connection
    close();
   // System.out.println(Close success );
  }
}
第二個類連線管理員。
package com.tarena.socketpool;

import java.lang.reflect.*;
import java.util.Properties;
/**
* <p>連線管理員</p>
* <p>Copyright: Copyright Tarena(c) 2005</p>
* <p>Company: Tarena</p>
* @author chengxing
* @version 1.0
*/
public class ConnectionManager {
  //測試程式預設的串連池實作類別
  public static final String PROVIDER_CLASS=com.tarena.socketpool.MyConnectionProvider;
  //測試程式的預設ip
  public static final String HOST=127.0.0.1;
  //測試程式的預設連接埠號碼
  public static final String PORT=9880;
  /**
   * 註冊鉤子程式的靜態匿名塊
   */
  static {
       //增加鉤子控制資源的釋放周期
       Runtime runtime = Runtime.getRuntime();
       Class c = runtime.getClass();
       try {
           Method m = c.getMethod(addShutdownHook, new Class[] { Thread.class } );
           m.invoke(runtime, new Object[] { new ShutdownThread() });
       }
       catch (NoSuchMethodException e) {
         e.printStackTrace();
           // Ignore -- the user might not be running JDK 1.3 or later.
       }
       catch (Exception e) {
           e.printStackTrace();
       }
   }
   /**
    * 預設的建構函式
    */
   public ConnectionManager() {
   }
   /**
    * 得到並初始化一個串連池
    * 串連池的實作類別通過系統參數來傳遞進來,通過命令列-DConnectionProvider=YourImplClass
    * 如果沒有指定的實現的話,則採用系統預設的實作類別
    * 通過命令列傳入的參數列表如下
    * 對方主機名稱-DHost=192.168.0.200
    * 對方連接埠號碼 -DPort=9880
    * 最小串連數  -DMax_style='font-size:10px'0
    * 最大連結數 -DMin_style='font-size:14px'0
    * 以上的值可以改變,但是參數不能改變,
    * 最大連結數和最小串連數可以省略,預設值分別為20和10
    * @return ConnectionProvider
    */
   public static ConnectionProvider getConnectionProvider()throws Exception{
     String provider_class=System.getProperty(ConnectionProvider);
     if(provider_class==null)provider_class=PROVIDER_CLASS;

     String host=System.getProperty(Host);
     if(host==null)host=HOST;

     String port=System.getProperty(port);
     if(port==null)port=PORT;

     String max_size=System.getProperty(Max_size);
     String min_size=System.getProperty(Min_size);

     Properties pro=new Properties();
     pro.setProperty(ConnectionProvider.SERVER_IP,host);
     pro.setProperty(ConnectionProvider.SERVER_PORT,port);
     if(max_size!=null)pro.setProperty(ConnectionProvider.MAX_SIZE,max_size);
     if(min_size!=null)pro.setProperty(ConnectionProvider.MIN_SIZE,min_size);
     //通過反射得到實作類別
     System.out.println(provider_class);
     System.out.flush();
     Class provider_impl=Class.forName(provider_class);
     //由於是單子模式,採用靜態方法回調
     Method m=provider_impl.getMethod(newInstance,new Class[]{java.util.Properties.class});
     ConnectionProvider provider=null;
     try{
        provider = (ConnectionProvider) m.invoke(provider_impl, new Object[]{pro});
     }catch(Exception e){
       e.printStackTrace();
     }

     return provider;
   }
   /**
    *
    * <p>一個鉤子的線程: 在程式結束的時候調用登出串連池</p>
    * <p>Description: </p>
    * <p>Copyright: Copyright Tarena(c) 2005</p>
    * <p>Company: Tarena</p>
    * @author chengxing
    * @version 1.0
    */
   private static class ShutdownThread extends Thread {
          public void run() {
            try{
              ConnectionProvider provider = ConnectionManager.getConnectionProvider();
              if (provider != null) {
                provider.destroy();
              }
            }catch(Exception e){
              e.printStackTrace();
            }
          }
      }

}

第三個類,串連池的介面定義
package com.tarena.socketpool;

import java.net.*;
import java.util.*;
import java.io.IOException;

/**
*
* <p>定義的抽象類別,所有的子類必須單子模式去實現,
* 統一方法為public ConnectionProvider newInstance();
* 串連提供器的抽象介面,每一個實現它的子類最好都是JAVABEAN,
* 這樣它的方法就可以是被外界控制</p>
* @see JiveBeanInfo
* <p>Copyright: Copyright Tarena(c) 2005</p>
* <p>Company: Tarena</p>
* @author chengxing
* @version 1.0
*/
public interface
    ConnectionProvider {
  public static final String SERVER_IP = SERVER_IP_ADDRESS;
  public static final String SERVER_PORT = SERVER_IP_PORT;
  public static final String MAX_SIZE = MAX_SIZE;
  public static final String MIN_SIZE = MIN_SIZE;

  /**
   *判斷串連池內是否有串連
   * @return true 有串連返回true,否則返回false
   */
  public boolean isPooled();

  /**
   * 當此方法被調用的時候提供一個 socket
   * @see Socket
   * @return Socket a Connection object.
   */
  public Socket getConnection() throws java.net.SocketException;

  /**
   * 串連池初始化
   */
  public void init() throws UnknownHostException, IOException;

  /**
   * 串連池重新啟動
   */
  public void restart() throws UnknownHostException, IOException;

  /**
   * 登出串連池
   */
  public void destroy();
}
第四個類MyConnectionProvider,自己寫的一個串連池的簡單實現
package com.tarena.socketpool;

import java.util.*;
import java.net.*;
import java.net.SocketException;
import java.io.IOException;

/**
*
* <p>這是一個連線管理員的簡單實現</p>
* <p>Description: implements the Interface ConnectionProvider</p>
* <p>Copyright: Copyright Tarena(c) 2005</p>
* <p>Company: Tarena</p>
* @author chengxing
* @version 1.0
*/
public class MyConnectionProvider
    implements ConnectionProvider {

  private Properties pro = null;
  private static ConnectionProvider provider = null;
  private static Object object_lock = new Object();
  private String ip;
  private String port;

  /**
   * 預設的最大串連數
   */
  private int max_size = 20;

  /**
   * 預設的最小串連數
   */
  private int min_size = 10;

  /**
   * Socket connection池數組
   */
  private ConnectionAdapter[] socketpool = null;

  /**
   * 構造對象的時候初始化串連池
   * @throws UnknownHostException 未知的主機異常
   * @throws IOException
   */
  private MyConnectionProvider(Properties pro) throws UnknownHostException,
      IOException {
    ip = pro.getProperty(SERVER_IP);
    port = pro.getProperty(SERVER_PORT);
    String max_size_s = pro.getProperty(MAX_SIZE);
    String min_size_s = pro.getProperty(MIN_SIZE);
    if (max_size_s != null) {
      max_size = Integer.parseInt(max_size_s);
    }
    if (min_size_s != null) {
      min_size = Integer.parseInt(min_size_s);
    }

    init(); //構造對象的時候初始化串連池
  }

  /**
   * 判斷是否已經池化
   * @return boolean 如果池化返回ture,反之返回false
   */
  public boolean isPooled() {
    if (socketpool != null) {
      return true;
    }
    else return false;
  }

  /**
   *返回一個串連
   * @return a Connection object.
   */
  public Socket getConnection() {
    Socket s = null;
    for (int i = 0; i < socketpool.length; i++) {
      if (socketpool[i] != null) {
        //如果有閒置串連,返回一個空閑串連,如果沒有,繼續迴圈
        if (socketpool[i].isFree()) {
          s = socketpool[i];
          return s;
        }
        else continue;
      }
      else { //如果串連為空白,證明超過最小串連數,重建串連
        try {
          s = socketpool[i] = new ConnectionAdapter(ip, Integer.parseInt(port));
        }
        catch (Exception e) {
          //never throw
        }
      }
    }
    //如果串連仍舊為空白的話,則超過了最大串連數
    if (s == null) {
      try { //產生普通串連,由用戶端自行關閉,釋放資源,不再由串連池管理
        s = new Socket(ip, Integer.parseInt(port));
      }
      catch (Exception e) { //此異常永遠不會拋出
      }
    }
    return s;
  }

  /**
   * 初始化串連池
   * @throws UnknownHostException 主機ip找不到
   * @throws IOException 此連接埠號碼上無server監聽
   */
  public void init() throws UnknownHostException, IOException {

    socketpool = new ConnectionAdapter[max_size];
    for (int i = 0; i < min_size; i++) {
      socketpool[i] = new ConnectionAdapter(ip, Integer.parseInt(port));
      System.out.print( . );
    }
    System.out.println();
    System.out.println(System init success ....);
  }

  /**
   * 重新啟動串連池
   * @throws UnknownHostException
   * @throws IOException
   */
  public void restart() throws UnknownHostException, IOException {
  destroy();
  init();
  }

  /**
   * 登出此串連池
   */
  public void destroy() {
    for (int i = 0; i < socketpool.length; i++) {
      if (socketpool[i] != null) {
        ConnectionAdapter adapter = (ConnectionAdapter) socketpool[i];
        adapter.destroy();
        System.out.print( . );
      }
    }
    System.out.println(\ndestory success ....);
  }
  /**
   * 靜態方法,產生此串連池實現的對象
   * @param pro Properties 此串連池所需要的所有參數的封裝
   * @throws UnknownHostException 主機無法找到
   * @throws IOException 與伺服器無法建立串連
   * @return ConnectionProvider 返回父類ConnectionProvider
   */
  public static ConnectionProvider newInstance(java.util.Properties pro) throws
      UnknownHostException, IOException {
    if (provider == null) {
      synchronized (object_lock) {
        if (provider == null) {
          provider = new MyConnectionProvider(pro);
        }
      }
    }
    return provider;
  }
  /**
   *設定系統屬性 通過封裝系統properties對象來封裝所需要的不同值
   * SERVER_IP,SERVER_PORT,MAX_SIZE,MIN_SIZE等父類定義的不同的參數
   * @param pro Properties 傳進來的系統屬性
   */
  public void setProperties(Properties pro) {
    this.pro = pro;
  }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.