1

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

我已经完成了完整的 java swing 应用程序的编写,现在想优化它的性能。欣赏任何见解,如果问题太天真,请原谅。

谢谢!

4

2 回答 2

4

您还没有说您是否需要函数的任何返回值,但考虑到它们访问数据库的事实,这似乎很有可能。一个非常好的和简单的解决方案是使用 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() 调用立即返回任务计算的未来值。任务在 submit() 调用时立即分派,并在后台运行。当然,您可以分派两个以上的任务。

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

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

于 2012-10-11T04:54:22.327 回答
1

您可以像这样调度 2 个线程:

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();
于 2012-10-04T18:25:16.827 回答