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 getQuantityFound开发者_如何学PythonLinks(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);
}
Use a Future with a Callable and 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
EDIT
Just to be clear - if a single query fails you now have nothing. If you can live with one result missing you just wrap the try - catch around every single get().
A get() is blocking (though optionally takes a time-out. So f2.get() will return immediately if in the mean time the results have been determine, otherwise it will wait untill f2 is also ready.
If you want to update a GUI immediately when a query is finished make updating the gui part of the callable, or use a SwingWorker in stead of a future.
Do be carefull with class member variables - concurrent access to shared state can be tricky. That's why I warned about the connection. If you use aa connection pool, give every call its own connection from the pool.
get() semantics state that when an exception occurs it's wrapped in the ExecutionException. Just get the cause() and determine what should be done.
As for an appropriate executor, I think a new Executors.newFixedThreadPool(4) will serve just fine, or use a newCachedThreadPool if you think more queries will follow. Queries aren't that intensive for your CPU (they are for the database server though) so a few extra threads are not really a problem as they are waiting for the database results anyway.
What you want to learn about Futures
and Callable
from the java.util.concurrent
package.
Here is a basic idea of what your code should look like:
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;
}
}
}
UPDATE: haven't notice that it is related to java
however I will leave here C# version:
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);
精彩评论