多线程优化执行效率

版权声明:欢迎转载,标明出处 https://blog.csdn.net/mz4138/article/details/82807378

在项目开发中,碰到了一些耗时任务的问题.

需要使用多线程,本文在使用原生JDK7的情况下优化

纯异步方式可以使用Java8或者引入RxJava框架进行编程。

普通任务

同步任务流程图如下

同步任务

假定场景如下:

  • taskA 耗时1秒
  • taskB 耗时2秒
  • taskC 耗时3秒

通常的操作就是遍历任务+执行任务, 代码如下

    // 任务A
    Runnable taskA = ()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
    // 任务B
        Runnable taskB = ()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
    // 任务C
        Runnable taskC = ()->{
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
    // 任务组
        Runnable [] taskArray = new Runnable[]{taskA,taskB,taskC};
    
        /**
         * 执行所有人物
         */
        @Test
        public void testSimple(){
            Date start = new Date();
            for (Runnable aTaskArray : taskArray) {
                aTaskArray.run();
            }
            Date end = new Date();
            System.out.println(end.getTime()-start.getTime());
        }

完成任务耗时6

多线程同步任务

为了提高运行效率,引入多线程,让等待的时间不再累计,而是合并。

最终执行的时间是耗时最长的任务执行时间

如下图所示,多个任务同时执行

多线程同步任务

代码

为了简便起见,使用了上面的任务组taskArray对象。

在实际使用中可以自己实现Runnable接口并传入CountDownLatch对象进行操作

    /**
     * 同步等待所有任务处理完成方案
     */
    @Test
    public void testSync() throws InterruptedException {
        final CountDownLatch countDownLatch = new CountDownLatch(taskArray.length);
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        Date start = new Date();
        for (Runnable aTaskArray : taskArray) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    aTaskArray.run();
                    countDownLatch.countDown();
                }
            });

        }
        countDownLatch.await();
        Date end = new Date();
        System.out.println(end.getTime()-start.getTime());
    }

执行时间: 3

使用 JDK5 提供的 CountDownLatch 进行同步优化

优点

  • 不用修改后续的代码(因为是同步的,后续的内容依赖于本次的内容也不影响)

缺点

  • 会造成调用线程等待

多线程异步任务

多线程异步任务

     /**
        * 异步回调方案
        * @throws InterruptedException
        */
       @Test
       public void testReturnAsync() throws InterruptedException {
           ExecutorService executorService = Executors.newFixedThreadPool(3);
           Date start = new Date();
           AtomicInteger atomicInteger = new AtomicInteger(taskArray.length);
           for (Runnable aTaskArray : taskArray) {
   
               executorService.execute(new Runnable() {
                   @Override
                   public void run() {
                       aTaskArray.run();
                       if(atomicInteger.decrementAndGet()==0){
                           Date end = new Date();
                           System.out.println(end.getTime()-start.getTime());
                       }
                   }
               });
   
           }
           System.out.println("等待子线程的结果");
           Thread.sleep(5*1000);
       }

执行时间: 3

优点

  • 不会造成调用线程等待

缺点:

  • 需要修改了法签名,需要传入Runnable对象,执行回调,后续的代码需要跟着修改

总结

  • 使用多线程异步还是同步主要的决定因素在于:调用线程是不是可以阻塞
  • 多线程同步和多线程异步的执行效率没有差别

猜你喜欢

转载自blog.csdn.net/mz4138/article/details/82807378