在Java中,如何在每个线程中运行不同的方法?

时间:2011-05-23 19:42:43

标签: java multithreading runnable

更新:我使用了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);
}

3 个答案:

答案 0 :(得分: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;
        }
    }

}

答案 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);