并行运行两个昂贵的数据库调用

时间:2012-10-04 18:15:25

标签: java multithreading performance swing

我有(比方说)2个函数,它们执行db-hit来获取大量数据。由于两个函数一个接一个地执行(通过相同的线程),所以花费的时间是T(f(1))+ T(f(2))。如何并行执行这两个函数(通过创建2个线程),以便所花费的总时间为:T(max(T(f1),T(f2))

我已经完成了编写完整的java swing应用程序,并希望现在可以优化它的性能。欣赏任何见解,并原谅这个问题是否太天真。

谢谢!

2 个答案:

答案 0 :(得分:3)

你还没有说过你的函数是否需要任何返回值,但考虑到它们访问数据库的可能性很大。一个非常好的简单解决方案是使用Executors和Futures。

完整的代码示例如下:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class FuturesExample {

  public interface ReturnTypeOne {}
  public interface ReturnTypeTwo {}

  public void runTwo() {
    ExecutorService executor = Executors.newFixedThreadPool(2);

    // Dispatch two tasks.
    Future<ReturnTypeOne> first = executor.submit(new Callable<ReturnTypeOne>() {
      @Override
      public ReturnTypeOne call() throws Exception {
        // Work, work, work...
        return null;
      }
    });
    Future<ReturnTypeTwo> second = executor.submit(new Callable<ReturnTypeTwo>() {
      @Override
      public ReturnTypeTwo call() throws Exception {
        // Work, work, work...
        return null;
      }
    });

    // Get the results.
    try {
      ReturnTypeOne firstValue = first.get();
      ReturnTypeTwo secondValue = second.get();
      // Combine the results.
    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (ExecutionException e) {
      e.printStackTrace();
    }
  }
}

它由两部分组成。首先将两个任务提交到线程池中。 每个ExecutorService.submit()调用立即返回任务计算的 future value 。在submit()调用时立即调度任务,它们在后台运行。当然,您可以派遣两个以上的任务。

在第二部分中,获得期货的价值。接下来是电话 到Future.get()阻塞当前线程,直到计算出值。这并不意味着 任何任务都被阻止,它们都在运行,线程只是等待给定任务完成并返回一个值。返回第一个值后,将进行第二次Future.get()调用。在这种情况下,它可能会或可能不会阻止。如果第二个任务已经完成(可能在第一个任务之前),则立即返回该值。如果第二个任务仍在运行,则调用将阻塞当前线程,直到计算出该值。

以上归结为您的主线程只会等待最长时间 运行任务。正是你需要的。

答案 1 :(得分:1)

您可以发送以下两个主题:

new Thread(new Runnable()
{
    @Override
    public void run()
    {
        // TODO Place your "f(1)" code here...

    }
}).start();

new Thread(new Runnable()
{
    @Override
    public void run()
    {
        // TODO Place your "f(2)" code here...

    }
}).start();