程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java基於TCP方法的二進制文件傳輸

Java基於TCP方法的二進制文件傳輸

編輯:關於JAVA

Java基於TCP方法的二進制文件傳輸。本站提示廣大學習愛好者:(Java基於TCP方法的二進制文件傳輸)文章只能為提供參考,不一定能成為您想要的結果。以下是Java基於TCP方法的二進制文件傳輸正文


1、引言

  池化技巧在Java中運用的很普遍,簡而論之,應用對象池存儲某個實例數受限制的實例,開辟者從對象池中獲得實例,應用完以後再換回對象池,從而在必定水平上削減了體系頻仍創立對象燒毀對象的開支。Java線程池和數據庫銜接池就是典范的運用,但並不是一切的對象都合適拿來池化,關於創立開支比擬小的對象拿來池化反而會影響機能,由於保護對象池也須要必定的資本開支,關於創立開支較年夜,又頻仍創立應用的對象,采取池化技巧會極年夜進步機能。

  業界有許多成熟的數據庫銜接池,好比C3P0,DBCP,Proxool和阿裡的Druid。許多和開源,在GitHub可以找到源碼,開辟者可以依據本身的需求聯合各類銜接池的特色和機能停止選擇。本文僅是為了懂得進修池化技巧,完成的一個簡略的數據庫銜接池,若有毛病,還望批駁斧正。

2、設計

重要類和接口

.ConnectionParam - 數據庫銜接池參數類,擔任設置裝備擺設數據庫銜接和銜接池相干參數。應用Builder完成。

    driver url user password - 銜接數據庫所需

    minConnection - 最小銜接數

    maxConnection - 最年夜銜接數

    minIdle - 最小余暇銜接數

    maxWait - 最長期待時光  

 private final String driver;

 private final String url;

 private final String user;

 private final String password;

 private final int minConnection;

 private final int maxConnection;

 private final int minIdle;

 private final long maxWait;

.ConnectionPool - 數據庫銜接池

    ConnectionPool結構辦法聲明為掩護,制止內部創立,交由ConnectionPoolFactory同一治理。

    ConnectionPool完成DataSource接口,從新getConnection()辦法。

    ConnectionPool持有兩個容器 - 一個Queue存儲余暇的Connection,另外一個Vector(斟酌到同步)存儲正在應用的Connection。

    當開辟者應用數據庫銜接時,從Queue中獲得,沒有則前往空;應用完成close銜接時,則放回Vector。

    ConnectionPool供給了一個簡略的基於minIdle和maxConnection的靜態擴容機制。

 private static final int INITIAL_SIZE = 5;

 private static final String CLOSE_METHOD = "close";

 private static Logger logger;

 private int size;

 private ConnectionParam connectionParam;

 private ArrayBlockingQueue<Connection> idleConnectionQueue;

 private Vector<Connection> busyConnectionVector;

.ConnectionPoolFactory - 銜接池治理類

  ConnectionPoolFactory持有一個靜態ConcurrentHashMap用來存儲銜接池對象。

  ConnectionPoolFactory許可創立多個分歧設置裝備擺設分歧數據庫的銜接池。

  開辟者初次須要應用特定的稱號注冊(綁定)銜接池,今後每次從指定的銜接池獲得Connection。

  假如銜接池不再應用,開辟者可以刊出(解綁)銜接池。

 private static Map<String, ConnectionPool> poolMap = new ConcurrentHashMap<>();

 public static Connection getConnection(String poolName) throws SQLException {
  nameCheck(poolName);
  ConnectionPool connectionPool = poolMap.get(poolName);
  return connectionPool.getConnection();
 }

 public static void registerConnectionPool(String name, ConnectionParam connectionParam) {
  registerCheck(name);
  poolMap.put(name, new ConnectionPool(connectionParam));
 }

 // Let GC
 public static void unRegisterConnectionPool(String name) {
  nameCheck(name);
  final ConnectionPool connectionPool = poolMap.get(name);
  poolMap.remove(name);
  new Thread(new Runnable() {
   @Override
   public void run() {
    connectionPool.clear();
   }
  }).start();
 }

焦點代碼

   數據庫銜接池焦點代碼在於getConnection()辦法,平日,開辟者處置完數據庫操作後,都邑挪用close()辦法,Connection此時應當被封閉並釋放資本。而在數據庫銜接池中,用戶挪用close()辦法,不該直接封閉Connection,而是要放回池中,反復應用,這裡就用到Java靜態署理機制,getConnection前往的其實不是“真正”的Connection,而是自界說的署理類(此處應用匿名類),當用戶挪用close()辦法時,停止攔阻,放回池中。有關靜態署理,可以參看另外一篇博客《Java靜態署理簡略運用》

 @Override
 public Connection getConnection() throws SQLException {
  try {
   final Connection connection = idleConnectionQueue.poll(connectionParam.getMaxWait(), TimeUnit.MILLISECONDS);
   if (connection == null) {
    logger.info(emptyMsg());
    ensureCapacity();
    return null;
   }
   busyConnectionVector.add(connection);
   return (Connection) Proxy.newProxyInstance(this.getClass().getClassLoader(),
     new Class[]{Connection.class}, new InvocationHandler() {
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       if (!method.getName().equals(CLOSE_METHOD)) {
        return method.invoke(connection, args);
       } else {
        idleConnectionQueue.offer(connection);
        busyConnectionVector.remove(connection);
        return null;
       }
      }
     });
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  return null;
 }

2、應用

  起首用戶構建數據庫銜接池參數(ConnectionParam),包含driver、url、user、password必需項,可以自界說minConnection、maxConnection等可選項,假如不設置,則應用體系默許值,這是應用Builder構建含有年夜量屬性的利益,個中包含必需屬性和可選屬性。然後向ConnectionPoolFactory應用特定的稱號注冊銜接池,最初經由過程挪用ConnectionPoolFactory靜態工場辦法獲得Connection。   

 String driver = "com.mysql.jdbc.Driver";
  String url = "jdbc:mysql://localhost:3306/test";
  String user = "root";
  String password = "root";

  ConnectionParam connectionParam = new ConnectionParam.ConnectionParamBuilder(driver, url, user, password).build();
  ConnectionPoolFactory.registerConnectionPool("test", connectionParam);
  Connection connection = ConnectionPoolFactory.getConnection("test");


3、代碼

.ParamConfiguration

package database.config;

import java.io.Serializable;

/**
 * DataBase Connection Parameters
 * Created by Michael Wong on 2016/1/18.
 */
public class ParamConfiguration implements Serializable {

 public static final int MIN_CONNECTION = 5;

 public static final int MAX_CONNECTION = 50;

 public static final int MIN_IDLE = 5;

 public static final long MAX_WAIT = 30000;

 private ParamConfiguration() {}

}

.Builder

package database;

/**
 * Builder
 * Created by Michael Wong on 2016/1/18.
 */
public interface Builder<T> {

 T build();

}

.ConnectionParam

package database;

import database.config.ParamConfiguration;

/**
 * DataBase Connection Parameters
 * Created by Michael Wong on 2016/1/18.
 */
public class ConnectionParam {

 private final String driver;

 private final String url;

 private final String user;

 private final String password;

 private final int minConnection;

 private final int maxConnection;

 private final int minIdle;

 private final long maxWait;

 private ConnectionParam(ConnectionParamBuilder builder) {
  this.driver = builder.driver;
  this.url = builder.url;
  this.user = builder.user;
  this.password = builder.password;
  this.minConnection = builder.minConnection;
  this.maxConnection = builder.maxConnection;
  this.minIdle = builder.minIdle;
  this.maxWait = builder.maxWait;
 }

 public String getDriver() {
  return this.driver;
 }

 public String getUrl() {
  return this.url;
 }

 public String getUser() {
  return this.user;
 }

 public String getPassword() {
  return this.password;
 }

 public int getMinConnection() {
  return this.minConnection;
 }

 public int getMaxConnection() {
  return this.maxConnection;
 }

 public int getMinIdle() {
  return this.minIdle;
 }

 public long getMaxWait() {
  return this.maxWait;
 }

 public static class ConnectionParamBuilder implements Builder<ConnectionParam> {

  // Required parameters
  private final String driver;

  private final String url;

  private final String user;

  private final String password;

  // Optional parameters - initialized to default value
  private int minConnection = ParamConfiguration.MIN_CONNECTION;

  private int maxConnection = ParamConfiguration.MAX_CONNECTION;

  private int minIdle = ParamConfiguration.MIN_IDLE;

  // Getting Connection wait time
  private long maxWait = ParamConfiguration.MAX_WAIT;

  public ConnectionParamBuilder(String driver, String url, String user, String password) {
   this.driver = driver;
   this.url = url;
   this.user = user;
   this.password = password;
  }

  public ConnectionParamBuilder minConnection(int minConnection) {
   this.minConnection = minConnection;
   return this;
  }

  public ConnectionParamBuilder maxConnection(int maxConnection) {
   this.maxConnection = maxConnection;
   return this;
  }

  public ConnectionParamBuilder minIdle(int minIdle) {
   this.minIdle = minIdle;
   return this;
  }

  public ConnectionParamBuilder maxWait(int maxWait) {
   this.maxWait = maxWait;
   return this;
  }

  @Override
  public ConnectionParam build() {
   return new ConnectionParam(this);
  }

 }

}

.ConnectionPool

package database.factory;

import database.ConnectionParam;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

/**
 * Connection Pool
 * Created by Michael Wong on 2016/1/18.
 */
public class ConnectionPool implements DataSource {

 private static final int INITIAL_SIZE = 5;

 private static final String CLOSE_METHOD = "close";

 private static Logger logger;

 private int size;

 private ConnectionParam connectionParam;

 private ArrayBlockingQueue<Connection> idleConnectionQueue;

 private Vector<Connection> busyConnectionVector;

 protected ConnectionPool(ConnectionParam connectionParam) {
  this.connectionParam = connectionParam;
  int maxConnection = connectionParam.getMaxConnection();
  idleConnectionQueue = new ArrayBlockingQueue<>(maxConnection);
  busyConnectionVector = new Vector<>();
  logger = Logger.getLogger(this.getClass().getName());
  initConnection();
 }

 private void initConnection() {
  int minConnection = connectionParam.getMinConnection();
  int initialSize = INITIAL_SIZE < minConnection ? minConnection : INITIAL_SIZE;
  try {
   Class.forName(connectionParam.getDriver());
   for (int i = 0; i < initialSize + connectionParam.getMinConnection(); i++) {
    idleConnectionQueue.put(newConnection());
    size++;
   }
  } catch (Exception e) {
   throw new ExceptionInInitializerError(e);
  }
 }

 @Override
 public Connection getConnection() throws SQLException {
  try {
   final Connection connection = idleConnectionQueue.poll(connectionParam.getMaxWait(), TimeUnit.MILLISECONDS);
   if (connection == null) {
    logger.info(emptyMsg());
    ensureCapacity();
    return null;
   }
   busyConnectionVector.add(connection);
   return (Connection) Proxy.newProxyInstance(this.getClass().getClassLoader(),
     new Class[]{Connection.class}, new InvocationHandler() {
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       if (!method.getName().equals(CLOSE_METHOD)) {
        return method.invoke(connection, args);
       } else {
        idleConnectionQueue.offer(connection);
        busyConnectionVector.remove(connection);
        return null;
       }
      }
     });
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  return null;
 }

 private Connection newConnection() throws SQLException {
  String url = connectionParam.getUrl();
  String user = connectionParam.getUser();
  String password = connectionParam.getPassword();
  return DriverManager.getConnection(url, user, password);
 }

 protected int size() {
  return size;
 }

 protected int idleConnectionQuantity() {
  return idleConnectionQueue.size();
 }

 protected int busyConnectionQuantity() {
  return busyConnectionVector.size();
 }

 private void ensureCapacity() throws SQLException {
  int minIdle = connectionParam.getMinIdle();
  int maxConnection = connectionParam.getMaxConnection();
  int newCapacity = size + minIdle;
  newCapacity = newCapacity > maxConnection ? maxConnection : newCapacity;
  int growCount = 0;
  if (size < newCapacity) {
   try {
    for (int i = 0; i < newCapacity - size; i++) {
     idleConnectionQueue.put(newConnection());
     growCount++;
    }
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  size = size + growCount;
 }

 protected void clear() {
  try {
   while (size-- > 0) {
    Connection connection = idleConnectionQueue.take();
    connection.close();
   }
  } catch (InterruptedException | SQLException e) {
   e.printStackTrace();
  }
 }

 private String emptyMsg() {
  return "Database is busy, please wait...";
 }

 @Override
 public Connection getConnection(String username, String password) throws SQLException {
  return null;
 }

 @Override
 public PrintWriter getLogWriter() throws SQLException {
  return null;
 }

 @Override
 public void setLogWriter(PrintWriter out) throws SQLException {

 }

 @Override
 public void setLoginTimeout(int seconds) throws SQLException {

 }

 @Override
 public int getLoginTimeout() throws SQLException {
  return 0;
 }

 @Override
 public Logger getParentLogger() throws SQLFeatureNotSupportedException {
  return null;
 }

 @Override
 public <T> T unwrap(Class<T> iface) throws SQLException {
  return null;
 }

 @Override
 public boolean isWrapperFor(Class<?> iface) throws SQLException {
  return false;
 }

}

.ConnectionPoolFactory

package database.factory;

import database.ConnectionParam;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Connection Pool Factory
 * Created by Michael Wong on 2016/1/18.
 */
public class ConnectionPoolFactory {

 private ConnectionPoolFactory() {}

 private static Map<String, ConnectionPool> poolMap = new ConcurrentHashMap<>();

 public static Connection getConnection(String poolName) throws SQLException {
  nameCheck(poolName);
  ConnectionPool connectionPool = poolMap.get(poolName);
  return connectionPool.getConnection();
 }

 public static void registerConnectionPool(String name, ConnectionParam connectionParam) {
  registerCheck(name);
  poolMap.put(name, new ConnectionPool(connectionParam));
 }

 // Let GC
 public static void unRegisterConnectionPool(String name) {
  nameCheck(name);
  final ConnectionPool connectionPool = poolMap.get(name);
  poolMap.remove(name);
  new Thread(new Runnable() {
   @Override
   public void run() {
    connectionPool.clear();
   }
  }).start();
 }

 public static int size(String poolName) {
  nameCheck(poolName);
  return poolMap.get(poolName).size();
 }

 public static int getIdleConnectionQuantity(String poolName) {
  nameCheck(poolName);
  return poolMap.get(poolName).idleConnectionQuantity();
 }

 public static int getBusyConnectionQuantity(String poolName) {
  nameCheck(poolName);
  return poolMap.get(poolName).busyConnectionQuantity();
 }

 private static void registerCheck(String name) {
  if (name == null) {
   throw new IllegalArgumentException(nullName());
  }
 }

 private static void nameCheck(String name) {
  if (name == null) {
   throw new IllegalArgumentException(nullName());
  }
  if (!poolMap.containsKey(name)) {
   throw new IllegalArgumentException(notExists(name));
  }
 }

 private static String nullName() {
  return "Pool name must not be null";
 }

 private static String notExists(String name) {
  return "Connection pool named " + name + " does not exists";
 }

}

4、測試
JUnit單位測試

package database.factory;

import database.ConnectionParam;
import org.junit.Test;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;

/**
 * ConnectionPoolFactory Test
 * Created by Michael Wong on 2016/1/20.
 */
public class ConnectionPoolFactoryTest {

 @Test
 public void testGetConnection() throws SQLException {

  String driver = "com.mysql.jdbc.Driver";
  String url = "jdbc:mysql://localhost:3306/test";
  String user = "root";
  String password = "root";

  ConnectionParam connectionParam = new ConnectionParam.ConnectionParamBuilder(driver, url, user, password).build();
  ConnectionPoolFactory.registerConnectionPool("test", connectionParam);

  List<Connection> connectionList = new ArrayList<>();

  for(int i = 0; i < 12; i++) {
   connectionList.add(ConnectionPoolFactory.getConnection("test"));
  }

  print();

  close(connectionList);

  print();

  connectionList.clear();

  for(int i = 0; i < 12; i++) {
   connectionList.add(ConnectionPoolFactory.getConnection("test"));
  }

  print();

  close(connectionList);

  ConnectionPoolFactory.unRegisterConnectionPool("test");

 }

 @Test(expected = IllegalArgumentException.class)
 public void testException() {
  try {
   ConnectionPoolFactory.getConnection("test");
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }

 private void close(List<Connection> connectionList) throws SQLException {
  for(Connection conn : connectionList) {
   if (conn != null) {
    conn.close();
   }
  }
 }

 private void print() {
  System.out.println("idle: " + ConnectionPoolFactory.getIdleConnectionQuantity("test"));
  System.out.println("busy: " + ConnectionPoolFactory.getBusyConnectionQuantity("test"));
  System.out.println("size: " + ConnectionPoolFactory.size("test"));
 }

}

以上就是本文的全體內容,願望對年夜家的進修有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved