1

更新:私はextraneonとJarrodRobersonによる回答を組み合わせて使用​​しました。

現在、同時に実行したい4つのメソッドがあります。それらはデータベースへの4つのクエリです。

4つのクラスを実装する必要があります。それぞれrun()に目的のクエリを含むクラスがありますか、それともこれを行う別の方法がありますか?

編集:これらのメソッドはプログラムの統計を更新し、StatisticsDBと呼ばれるクラスに実装されます(以下のメソッドはこれよりも大きいため、Facadeからのものです)。backgroudのスレッドで実行される統計を更新するクラスがあります。私はこのようなものが欲しいので、スレッドごとに1つの接続にすることができます。

public void updateStatistics(){
    //these methods running at same time
    pages = getQuantityVisitedPages();
    links = getQuantityFoundLinks();
    blinks = getQuantityBrokenLinks();
    flinks = getQuantityFilteredLinks();
}

public String getQuantityVisitedPages(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityVisitedPages(conn);
}

public String getQuantityFoundLinks(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityFoundLinks(conn);
}

public String getQuantityBrokenLinks(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityFilteredLinks(conn);
}

public String getQuantityFilteredLinks(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityFilteredLinks(conn);
}
4

3 に答える 3

3

CallableとExecutorServiceでFutureを使用します。

// Don't use the connection on all queries at the same time
// unless that's allowed.
Future<String> f1 = executor.submit(new Callable<String>() {
     public String call() {
         return getQuantityVisitedPages( createConnection() );
     }});
Future<String> f2 = executor.submit(new Callable<String>() {
     public String call() {
         return getQuantityFoundLinks( createConnection() );
     }});


 try {
   // wait until f1 is finished and get the result
   // in the mean time all queries are running
   String qvp = f1.get(); 
   String qfl = f2.get();
 } catch (ExecutionException ex) { cleanup(); return; }

 // do something with found values

編集

明確にするために、単一のクエリが失敗した場合、今は何もありません。1つの結果が欠落している状態で生きることができる場合は、tryをラップするだけです-すべてのget()をキャッチします。

get()はブロックしています(ただし、オプションでタイムアウトが発生します。そのため、結果が決定された場合はf2.get()がすぐに返されます。それ以外の場合は、f2の準備ができるまで待機します。

クエリが終了したらすぐにGUIを更新する場合は、呼び出し可能オブジェクトのGUI部分を更新するか、将来の代わりにSwingWorkerを使用します。

クラスメンバー変数には注意してください。共有状態への同時アクセスには注意が必要です。そのため、接続について警告しました。接続プールを使用する場合は、すべての呼び出しにプールからの独自の接続を与えます。

get()セマンティクスは、例外が発生すると、ExecutionExceptionにラップされることを示します。cause()を取得し、何をすべきかを判断するだけです。

適切なエグゼキュータについては、新しいExecutors.newFixedThreadPool(4)で問題なく機能するか、さらにクエリが続くと思われる場合はnewCachedThreadPoolを使用すると思います。クエリはCPUに対してそれほど集中的ではないため(ただし、データベースサーバーに対しては)、データベースの結果を待機しているため、いくつかの追加のスレッドは実際には問題になりません。

于 2011-05-23T19:59:07.930 に答える
3

Futuresパッケージについて、そしてパッケージCallableから学びたいことjava.util.concurrent

コードがどのように見えるかについての基本的な考え方は次のとおりです。

import java.sql.ResultSet;
import java.util.concurrent.*;

public class Main
{
    public static void main(final String[] args)
    {
        final ExecutorService es = Executors.newFixedThreadPool(5);
        final Future<ResultSet> rs1 = es.submit(new Query01());
        final Future<ResultSet> rs2 = es.submit(new Query02());
        final Future<ResultSet> rs3 = es.submit(new Query03());
        final Future<ResultSet> rs4 = es.submit(new Query04());

        // then you can test for completion with methods on
        // rs1, rs2, rs3, rs4 and get the ResultSet with rs1.get();

        while ( !f1.isDone() && !f2.isDone() && !f3.isDone() && !f4.isDone() )
        {
            // handle results that are complete
        }
    }

    public static class Query01 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }
     public static class Query02 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }
        public static class Query03 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }
        public static class Query04 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }

}
于 2011-05-23T19:52:28.127 に答える
2

更新: Javaに関連していることに気づいていません

ただし、ここではC#バージョンを残します。

Task<string> task1 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityVisitedPages(conn);
  }
Task<string> task2 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityFoundLinks(conn);
  }
Task<string> task3 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityBrokenLinks(conn);
  }
Task<string> task4 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityFilteredLinks(conn);
  }
Task.WaitAll(task1, task2, task3, task4);
Console.WriteLine(task1.Result);
Console.WriteLine(task2.Result);
Console.WriteLine(task3.Result);
Console.WriteLine(task4.Result);
于 2011-05-23T19:51:09.893 に答える