更新:我使用了extraneon和Jarrod Roberson的答案。
我目前有四种方法可以同时运行。它们是对数据库的四个查询。
我需要实现四个类,每个类都带有一个带有所需查询的run()
或另外一种方法来执行此操作?
编辑:这些方法将更新程序中的统计信息,并在名为StatisticsDB的类中实现(以下这些方法来自Facade,因为方法大于此)。我有一个类将更新在backgroud中的线程中运行的统计信息。我想要这样的东西,每个线程可以是一个连接。
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);
}
答案 0 :(得分: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;
}
}
}
答案 1 :(得分: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 - catch包围在每一个get()。
get()是阻塞的(虽然可选地需要超时。因此,如果在确定结果的同时,f2.get()将立即返回,否则它将等待直到f2也准备就绪。
如果要在查询完成后立即更新GUI,请更新可调用的gui部分,或使用SwingWorker代替将来。
小心使用类成员变量 - 并发访问共享状态可能很棘手。这就是我警告这种联系的原因。如果您使用连接池,请从池中为每个呼叫提供自己的连接。
get()语义声明当发生异常时,它包含在ExecutionException中。只需获取cause()并确定应该做什么。
至于适当的执行者,我认为new Executors.newFixedThreadPool(4)可以正常使用,或者如果您认为会有更多查询,请使用newCachedThreadPool。查询对你的CPU来说不是那么密集(虽然它们是针对数据库服务器的),所以一些额外的线程并不是真正的问题,因为它们无论如何都在等待数据库结果。
答案 2 :(得分:2)
UPDATE:没有注意到它与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);