2016-08-21 24 views
1
私は、マルチスレッドのアプローチを使用して、いくつかのクエリを実行しようとしています

は、しかし、私は私のプログラムは、私の実装であるは、JDBCおよびマルチスレッド

SELECT * FROM TABLE WHERE ID = 123' 

のような単純なSELECTステートメントを実行するのに約5分かかりますので、私は何か間違ったことをやっていると思います私は1つの接続オブジェクトを使用しています。私の実行方法

public void run() { 
    runQuery(conn, query); 
} 

によってRunQueryメソッドmainメソッドで最後に

public void runQuery(Connection conn, String queryString){ 
    Statement statement; 
    try { 
      statement = conn.createStatement(); 
      ResultSet rs = statement.executeQuery(queryString); 
      while (rs.next()) {} 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } 
} 

、私は以下のスニペットを使用してスレッドを開始。

MyThread bmthread = new MyThread(conn, query); 
ArrayList<Thread> allThreads = new ArrayList<>(); 
double start = System.currentTimeMillis(); 
    int numberOfThreads = 1; 
    for(int i=0; i<=numberOfThreads; i++){ 
     Thread th = new Thread(bmthread); 
     th.setName("Thread "+i); 
     System.out.println("Starting Worker "+th.getName()); 
     th.start(); 
     allThreads.add(th); 
    } 

    for(Thread t : allThreads){ 
     try { 
      t.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
double end = System.currentTimeMillis(); 
double total = end - start; 
System.out.println("Time taken to run threads "+ total); 

アップデート:スレッドごとに別々の接続を使用しています。

ArrayList<Connection> sqlConn = new ArrayList<>(); 
    for(int i =0; i<10; i++){ 
     sqlConn.add(_ut.initiateConnection(windowsAuthURL, driver)); 
    } 
loop: 
    MyThread bmthread = new MyThread(sqlConn.get(i), query); 
+0

もう少し情報を追加できますか?どのデータベースを使用していますか?どのように接続を構築していますか?すべてのスレッドの内容がなくても1回のクエリでどれくらい時間がかかりますか? – adamM

+0

私はSQL Server 2008を使用しています。スレッドのものがなければ、コードはミリ秒単位で実行されます。実際は1秒未満です。 – fanbondi

答えて

3

rohivatsとAsaphによれば、1つの接続で1つのスレッドのみが使用されなければならないと言われています。 c3p0とsimilarsがほぼ放棄されていることを考慮すると、私はHirakiCPを使用します。これは本当に高速で信頼性があります。

あなたは非常にシンプルな何かをしたい場合は、たとえば、(たとえば、LinkedListのように)スレッドセーフなコレクションを使用して実際に簡単な接続プールを実装することができます:

public class CutrePool{ 
     String connString;  
     String user; 
     String pwd; 

     static final int INITIAL_CAPACITY = 50; 
     LinkedList<Connection> pool = new LinkedList<Connection>(); 
     public String getConnString() { 
      return connString; 
     } 
     public String getPwd() { 
      return pwd; 
     } 

     public String getUser() { 
      return user; 
     } 

     public CutrePool(String connString, String user, String pwd) throws SQLException { 
      this.connString = connString; 

      for (int i = 0; i < INITIAL_CAPACITY; i++) { 
       pool.add(DriverManager.getConnection(connString, user, pwd)); 
      } 
      this.user = user; 
      this.pwd = pwd; 
     } 

     public synchronized Connection getConnection() throws SQLException { 
      if (pool.isEmpty()) { 
       pool.add(DriverManager.getConnection(connString, user, pwd)); 
      } 
      return pool.pop(); 
     } 

     public synchronized void returnConnection(Connection connection) { 
      pool.push(connection); 
     } 
    } 

をあなたはのgetConnectionとreturnConnection方法を見ることができるようにに同期されますスレッドセーフであること。接続(conn = pool.getConnection();)を使用し、使用後に接続を返す/忘れることを忘れないでください(pool.returnConnection(conn);

+0

私は平明CPを見て、それがどのようになっているかを教えてくれるでしょう。 – fanbondi

+0

シングルトンパターンを使用して独自のプール接続を実装することもできますが、私はホイールを改革する大きなファンではありません: –

+0

本当に簡単な接続プールが必要な場合に備えて私の答えを編集しました。 –

2

すべてのスレッドで同じ接続オブジェクトを使用しないでください。各スレッドに専用のデータベース接続を与えます。

+0

私は各スレッドごとに異なる接続を使用しています。私の質問の更新を参照してください。今は33秒かかります。私はSQL Serverの管理スタジオで実行する場合は、同じクエリは1秒かかる。 – fanbondi

+0

私はあなたの質問の中に後ろに一重引用符があることに気付きました。それはタイプミスですか?そのクエリ内の数字は一重引用符で囲まれていますか? – Asaph

+0

@Asha、ええ、それはタイプミスです! – fanbondi

1

Connectionは、一度に1つのクエリしか実行できません。パラレルでデータベース操作を実行するには、複数の接続が必要です。接続プールでDataSourceを使用し、各スレッドがプールからの接続を要求するようにしてください。

関連する問題