1

UPDATE: I have used a mix of the answers by extraneon and Jarrod Roberson.

I have currently four methods that I want to run at same time. They are four queries to database.

I need to implement four classes, each one with a run() with the desired query or there another way to do this?

EDIT: These methods will update statistics in the program and are implemented in a class called StatisticsDB (these methods below are from the Facade because the methods are greater than this). I have a class that will update the statistics that run in a thread in backgroud. I want something like this and can be one connection per thread.

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

Future与 Callable 和 ExecutorService 一起使用。

// 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

编辑

只是要清楚 - 如果单个查询失败,您现在什么都没有。如果您可以忍受缺少一个结果,您只需将 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中了解什么。Callablejava.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 回答