0

私はJavaには新しいが、一般的なプログラミングには新しくない。固定数を維持する方法

シナリオは、一度に最大n個の接続を持つことができ、接続の開閉は非常にコストがかかることです。

同じn個の接続を再利用して、コレクションに何かを残したいと思っています。

リクエストが来たら、私は接続をピックアップし、自分の仕事を行い、閉じずに接続を返します。次のリクエストが来たら、次に利用可能な接続を受け取ります。

すべての接続が使用中で、要求が来ると、接続が利用可能になるのを待つだけです。

最もクリーンなJavaソリューションは何でしょうか。私はコードが必要ない、私はちょうどいくつかのアイデアを探求する必要があります。いくつかのフレームワークは既にそれを行うことがあります、いくつかのJavaクラスはすでにその機能を提供することがあります。

アイデアをいただければ幸いです。

+0

何かへの接続? – MadProgrammer

+2

接続プールDBのようなものがあります.... – GirlEngineer23

+0

これらは外部のサーバーへのソケット接続です – GirlEngineer23

答えて

-1

データソースを使用して接続プール接続プールです。

私はあなたのプロジェクトに実装できるテストプログラムを提供しています。

MainFile

package TestPool; 

import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import org.apache.commons.dbcp2.BasicDataSource; 

public class TestConnPool { 

/** 
* @param args the command line arguments 
*/ 
public static void main(String[] args) { 
    Connection connection = null; 
    PreparedStatement statement = null; 
    ResultSet resultSet = null; 
    try { 
     BasicDataSource bds = DataSource.getInstance().getBds(); 
     connection = bds.getConnection();    
     statement = connection 
       .prepareStatement("select id from TestConnPool;"); 
     resultSet = statement.executeQuery();    
     while (resultSet.next()) { 
      System.out.println(resultSet.getString("id")); 
     } 

    } catch (SQLException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      if (resultSet != null) { 
       resultSet.close(); 
      } 
      if (statement != null) { 
       statement.close(); 
      } 
      if (connection != null) { 
       connection.close(); 
      } 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
    } 

} 
} 

データソースのサンプル・ファイルは以下の通りです。

package TestPool; 

import org.apache.commons.dbcp2.BasicDataSource; 

public class DataSource { 

    private static final String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver"; 
    private static final String DB_URL = "jdbc:mysql://localhost:3306/test"; 
    private static final String DB_USER = "root"; 
    private static final String DB_PASSWORD = "root"; 
    private static final int CONN_POOL_SIZE = 50; 
    private static final int MIN_CONN_POOL_SIZE = 30; 
    private static final int MAX_CONN_POOL_SIZE = 45; 

    private BasicDataSource bds = new BasicDataSource(); 

    private DataSource() { 
     //Set database driver name 
     bds.setDriverClassName(DRIVER_CLASS_NAME); 
     //Set database url 
     bds.setUrl(DB_URL); 
     //Set database user 
     bds.setUsername(DB_USER); 
     //Set database password 
     bds.setPassword(DB_PASSWORD); 
     //Set the connection pool size 
     bds.setInitialSize(CONN_POOL_SIZE); 
     //Set the connection minimum pool size 
     bds.setMinIdle(MIN_CONN_POOL_SIZE); 
     //Set the connection maximum pool size 
     bds.setMaxTotal(MAX_CONN_POOL_SIZE); 

    } 

    public static class DataSourceHolder { 
     private static final DataSource INSTANCE = new DataSource();   
    } 

    public static DataSource getInstance() { 
     return DataSourceHolder.INSTANCE; 
    } 

    public BasicDataSource getBds() { 
     return bds;   
    } 

    public void setBds(BasicDataSource bds) { 
     this.bds = bds; 
    } 
} 

あなたは最大最小プールサイズの大きさを割り当てることができます。

優位

あなたが接続を閉じると、それは実際に近くではありませんが、それは、接続プールに戻って与えられます。 接続プールは、指定した接続数を維持します。

はまたdbcp2のBasicDataSource

コモンズ-dbcp2-2.0.jar

コモンズ・ログ-1.2.jar

コモンズ-pool2-のために重要であり、瓶の下に使用します2.4.2.jar

mysql-connector-java-5.1.25.jar

これがあなたの問題を解決することを願っています。 :)

+0

これはデータベースへの接続ではありません。私は一般的なオブジェクトプーリングのいくつかの並べ替えが必要です。 – GirlEngineer23

+0

次に、Wait()&Notify()を使用できます。 perticular固有のキーを持つオブジェクトをハッシュマップに保存することができます。 –

0

私はあなたが接続プーリングに行くことをお勧めします。この場合、Connectionを複数のタスクに使用している場合は、プールに別々に記述します。 必要なときにプールから接続を取得します。それが完了したら、それをプールに戻します。この方法では、Connectionはスレッドセーフであり、矛盾を回避できます。 また、オープンとクローズ接続は、リソースのクラッシュにつながります。

-1

あなたは接続オブジェクトを作成するクラスの接続を作成し、それが

class Connection implements Callable<Connection> { 

    @Override 
    public Connection call() { 
     // Logic to get the connection 
     return new Connection(); 
    } 
} 

その後、タスクを送信してもらうん返すことができ

ExecutorService service = Executors.newFixedThreadPool(n); 

スレッドの固定数のエグゼキュータ・サービスを使用することができますプールからの将来の接続オブジェクト。

Future<Connection> future = service.submit(new Connection()); 
Connection conn = future.get(); 
+0

接続を作成するためだけにスレッドを開始するのは無駄です。ここにはプールがありません。 – EJP

0

HTTP Core NIOやNettyなどのフレームワークを使用してください。 HTTPCore NIOインスタンスの例では、以下のようにバックエンドに接続するワーカースレッドグループを作成できます。

ProxyConnPool connPool = createConnectionPool(connectingIOReactor); 
connPool.setMaxTotal(100); 
connPool.setDefaultMaxPerRoute(20); 

private static ProxyConnPool createConnectionPool(final ConnectingIOReactor connectingIOReactor) 
                            throws KeyManagementException, 
                            KeyStoreException, 
                            NoSuchAlgorithmException, 
                            CertificateException, 
                            FileNotFoundException, 
                            IOException { 
     ProxyConnPool proxyConnPool = null; 

     if (SECURE_BACKEND) { 
      clientSSLContext = 
           SSLUtil.createClientSSLContext(TRUST_STORE_LOCATION, 
                   TRUST_STORE_PASSWORD); 

      BasicNIOConnFactory connectionFactory = 
                new BasicNIOConnFactory(
                      clientSSLContext, 
                      null, 
                      ConnectionConfig.DEFAULT); 

      proxyConnPool = new ProxyConnPool(connectingIOReactor, connectionFactory, 5000); 
     } else { 
      proxyConnPool = new ProxyConnPool(connectingIOReactor, ConnectionConfig.DEFAULT); 
     } 

     return proxyConnPool; 
    } 

あなたはコードがこれに似たものになりますネッティーでHTTP core NIO reverse proxyNetty reverse Proxy

のための私のサンプルコードを見つけることができます。

// Configure the bootstrap. 
EventLoopGroup bossGroup = new NioEventLoopGroup(1); 
EventLoopGroup workerGroup = new NioEventLoopGroup(); 

これが役に立ちます。ハッピーコーディング!

+0

コードをフォーマットしていただけますか?ほとんど読めません。 – Gray

0

リクエストが来たら、私は接続をピックアップし、自分の仕事を行い、閉じずに接続を返します。次のリクエストが来たら、次に利用可能な接続を受け取ります。

すべてのスレッドで共有される単純なBlockingQueue<Connection>を使用します。あなたがConnectionオブジェクトの束を開き、キューに追加し、アプリケーションの開始時に

final BlockingQueue<Connection> connectionQueue = new LinkedBlockingQueue<Connection>(); 

for (int i = 0; i < NUM_CONNECTIONS_TO_START; i++) { 
    queue.put(new Connection()); 
} 

スレッドが、それはどれもがすぐに入手できなかった場合は、1つを待って、待ち行列からConnectionになるだろう、接続を取得するために行きます。 Connectionを使用した後、次のスレッドが持つためにキューに戻します。

// this will wait if there are no connections available 
Connection connection = queue.take(); 
try { 
    useTheConnection(connection); 
} finally { 
    // after we are done add it back to the queue 
    queue.put(connection); 
} 

このすべての難しい部分は、ソケットで何らかの種類のネットワーク例外が発生した場合です。あなたのスレッドはConnectionを正しく閉じてから、新しいキューをキューに追加する必要があります。おそらく次のようなものでしょう:

// this will wait if there are no connections available 
Connection connection = queue.take(); 
try { 
    useTheConnection(connection); 
} catch (Exception e) { 
    // assume the connection is bad 
    try { 
     connection.close(); 
    } catch (Exception e2) { 
     // ignore any exceptions here 
    } 
    // start a new fresh connection to add back to our queue 
    connection = new Connection(); 
} finally { 
    // after we are done add it back to the queue 
    queue.put(connection); 
} 
関連する問題