Использование 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
EDIT
Просто чтобы прояснить: если один запрос не удался, у вас теперь ничего нет. Если вы можете жить с одним пропущенным результатом, просто оберните попытку - ловите каждый get ().
get () блокирует (хотя необязательно занимает время ожидания. Таким образом, f2.get () немедленно вернется, если за это время будут определены результаты, в противном случае он будет ждать до тех пор, пока f2 также не будет готов.
Если вы хотите обновить GUI сразу после завершения запроса, сделайте обновление графической части вызываемой программы или используйте SwingWorker вместо будущего.
Будьте осторожны с переменными членов класса - одновременный доступ к общему состоянию может быть сложным. Вот почему я предупредил о связи. Если вы используете пул соединений, присваивайте каждому вызову свое собственное соединение из пула.
Семантика get () гласит, что при возникновении исключения оно включается в ExecutionException. Просто найдите причину () и определите, что нужно сделать.
Что касается соответствующего исполнителя, я думаю, что new Executors.newFixedThreadPool (4) будет работать просто отлично, или используйте newCachedThreadPool, если вы думаете, что последует больше запросов. Запросы не столь интенсивны для вашего ЦП (хотя и для сервера базы данных), поэтому несколько дополнительных потоков на самом деле не проблема, так как они все равно ждут результатов базы данных.