В Java, как запустить разные методы, по одному в каждом потоке? - PullRequest
1 голос
/ 23 мая 2011

ОБНОВЛЕНИЕ: Я использовал смесь ответов Экстранеона и Джаррода Роберсона.

В настоящее время у меня есть четыре метода, которые я хочу запустить одновременно. Это четыре запроса к базе данных.

Мне нужно реализовать четыре класса, каждый с run() с желаемым запросом или есть другой способ сделать это?

РЕДАКТИРОВАТЬ: Эти методы обновят статистику в программе и реализованы в классе с именем StatisticsDB (эти методы ниже от Фасада, потому что методы больше, чем это). У меня есть класс, который будет обновлять статистику, которая запускается в потоке в 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);
}

Ответы [ 3 ]

3 голосов
/ 23 мая 2011

Что вы хотите узнать о 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;
        }
    }

}
3 голосов
/ 23 мая 2011

Использование 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, если вы думаете, что последует больше запросов. Запросы не столь интенсивны для вашего ЦП (хотя и для сервера базы данных), поэтому несколько дополнительных потоков на самом деле не проблема, так как они все равно ждут результатов базы данных.

2 голосов
/ 23 мая 2011

ОБНОВЛЕНИЕ: не заметил, что это связано с 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...