【问题标题】:How to run different methods parallely如何并行运行不同的方法
【发布时间】:2013-08-12 08:10:09
【问题描述】:

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

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

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

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

【问题讨论】:

  • 在各自的线程下运行每个方法,假设它们不共享可变状态?
  • 感谢您的回复,您能否详细说明或提供任何示例链接:)
  • 既然你已经确定你需要线程,你的问题到底是什么?如何调用新线程?
  • 是的...因为这些是不同的业务逻辑。我不知道如何为此调用线程

标签: java multithreading parallel-processing


【解决方案1】:

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

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

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

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();
        }
    }

【讨论】:

    【解决方案2】:

    做这样的事情:

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

    这是一个简单的例子:

    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 提供a good introduction to Java Executors。此外,this book 非常棒,如果您在 java 中进行任何类型的线程处理。

    【讨论】:

    • 一切都很好,除了List&lt;Future&lt;Void&gt;&gt; futureList = executor.invokeAll(taskList); 之后的任何内容都不会被执行,所以这些计时器不起作用。
    • 并行调用所有方法,但是,它在方法 1 中创建线程 1,在方法 2 中创建线程 2,依此类推。它应该为所有方法创建线程 1。我们必须做的。 @Ireeder
    • 和关闭执行器,这里有可能吗?
    【解决方案3】:

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

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

    对所有方法都这样做。

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

    t1.join();
    

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

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

    【讨论】:

    • 对于所有 5 个方法需要创建 5 个线程并且在内部运行我们需要调用它们,这将使它们并行调用???
    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:

      看看 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/ 基本上,你必须创建一个 executorserice,一些扩展 Runnable 的类,然后调用它们

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 但这5个方法都有不同的业务逻辑
        • @user1037452 那么,使用线程池和“不同的业务逻辑”有什么问题呢?我不完全理解你的疑问。但是看起来你需要阅读一些关于java中并发的基本信息
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-14
        • 2019-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多