8

我有一个包含 5 种不同内部方法的 java 方法。为了提高性能,我想并行调用这些方法。

例如,使用线程并行运行method1、method2、...method5。

private void getInformation() throws SQLException,
            ClassNotFoundException, NamingException {
    method1();
    method2();
    method3();
    method4();
    method5();
}

但是这 5 种方法都有不同的业务逻辑。

4

6 回答 6

18

做这样的事情:

  1. 对于每个方法,创建一个包装该方法的 Callable 对象。
  2. 创建一个执行器(一个固定的线程池执行器应该没问题)。
  3. 将所有 Callables 放在一个列表中,并使用 Executor 调用它们。

这是一个简单的例子:

public void testThread()
{

   //create a callable for each method
   Callable<Void> callable1 = new Callable<Void>()
   {
      @Override
      public Void call() throws Exception
      {
         method1();
         return null;
      }
   };

   Callable<Void> callable2 = new Callable<Void>()
   {
      @Override
      public Void call() throws Exception
      {
         method2();
         return null;
      }
   };

   Callable<Void> callable3 = new Callable<Void>()
   {
      @Override
      public Void call() throws Exception
      {
         method3();
         return null;
      }
   };

   //add to a list
   List<Callable<Void>> taskList = new ArrayList<Callable<Void>>();
   taskList.add(callable1);
   taskList.add(callable2);
   taskList.add(callable3);

   //create a pool executor with 3 threads
   ExecutorService executor = Executors.newFixedThreadPool(3);

   try
   {
      //start the threads and wait for them to finish
      executor.invokeAll(taskList);
   }
   catch (InterruptedException ie)
   {
      //do something if you care about interruption;
   }

}

private void method1()
{
   System.out.println("method1");
}

private void method2()
{
   System.out.println("method2");
}

private void method3()
{
   System.out.println("method3");
}

确保每个方法不共享状态(如同一类中的常见可变字段),否则您可能会得到意想不到的结果。Oracle很好地介绍了 Java 执行器。此外,如果你在 Java 中做任何类型的线程,这本书也很棒。

于 2013-08-10T15:45:16.080 回答
5

要并行运行 method1,请执行以下操作:

Thread t1=new Thread() {
   public void run() {
       method1();
   }
};
t1.start();

对所有方法执行此操作。

要等待方法 1 完成,请执行

t1.join();

对于所有其他线程也是如此。

很多人会告诉你使用线程池,不要扩展线程——这一切现在对你来说意义不大。以这种方式掌握,然后才遵循该建议。

于 2013-08-11T18:08:57.140 回答
4

我有类似的要求。在特定操作中,我必须调用一组验证器方法,这些方法反过来验证某些组件。每个验证器过去都需要花费一定的时间并且不得不减少它并决定异步调用它。

确实有很多方法可以实现它,这是我解决的方法之一。

由于验证器大多不返回任何值,因此利用了 Runnable 类 lambda。在下面的示例addition中,方法将被异步和并行调用multiplysubtraction

public class MultiThreading {

        public static void addition() {
            System.out.println("Addition");
        }

        public static void multiply() {
            System.out.println("multiplication");
        }

        public static void subtraction() {
            System.out.println("subtraction");
        }

        public static void main(String[] args) {
            ExecutorService executor = Executors.newCachedThreadPool();

            Runnable callMultiply = () -> multiply();  //Create Runnable reference using lambda
            executor.execute(callMultiply);
            executor.execute(() -> addition()); //inline
            executor.execute(() -> subtraction());
            
            executor.shutdown();
        }
    }
于 2020-09-10T19:34:26.413 回答
0

您可以在 Java 中使用高级并发工具 - 线程池。但无论如何,您必须创建 Runnable 对象(任务),然后使用线程池的方法 - invokeAll()。请看Oracle并发教程

于 2013-08-10T14:33:35.987 回答
0

看看 java.util.concurrent http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html 和教程: http: //docs.oracle。 com/javase/tutorial/essential/concurrency/ 基本上,你必须创建一个执行器服务,一些扩展 Runnable 的类,然后调用它们

于 2013-08-10T14:39:10.027 回答
0

您必须使用 5 个不同的线程来并行执行您的方法,代码不难但很无聊。

您可能想看看 Gpars Tasks,它使编写并行代码变得更加容易和愉快。

http://gpars.org/1.0.0/guide/guide/dataflow.html#dataflow_tasks

于 2013-08-10T15:54:53.407 回答