多线程优化执行效率 梦里梦外; 2022-05-11 09:30 146阅读 0赞 ### 文章目录 ### * 普通任务 * 多线程同步任务 * * 代码 * 多线程异步任务 * 总结 在项目开发中,碰到了一些耗时任务的问题. 需要使用多线程,本文在使用原生JDK7的情况下优化 纯异步方式可以使用Java8或者引入RxJava框架进行编程。 # 普通任务 # 同步任务流程图如下 ![同步任务][E5_90_8C_E6_AD_A5_E4_BB_BB_E5_8A_A1.png] 假定场景如下: * 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`秒 # 多线程同步任务 # 为了提高运行效率,引入多线程,让等待的时间不再累计,而是合并。 最终执行的时间是`耗时最长的任务`执行时间 如下图所示,多个任务同时执行 ![多线程同步任务][E5_90_8C_E6_AD_A5_E5_A4_9A_E7_BA_BF_E7_A8_8B_E4_BB_BB_E5_8A_A1.png] ## 代码 ## 为了简便起见,使用了上面的`任务组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 进行同步优化 优点 * 不用修改后续的代码(因为是同步的,后续的内容依赖于本次的内容也不影响) 缺点 * 会造成调用线程等待 # 多线程异步任务 # ![多线程异步任务][E5_BC_82_E6_AD_A5_E5_A4_9A_E7_BA_BF_E7_A8_8B_E4_BB_BB_E5_8A_A1.png] /** * 异步回调方案 * @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对象,执行回调,后续的代码需要跟着修改 # 总结 # * 使用多线程异步还是同步主要的决定因素在于:`调用线程是不是可以阻塞` * 多线程同步和多线程异步的执行效率没有差别 [E5_90_8C_E6_AD_A5_E4_BB_BB_E5_8A_A1.png]: http://cdn.blog.shangwantong.com/java-core/thread/%E5%90%8C%E6%AD%A5%E4%BB%BB%E5%8A%A1.png [E5_90_8C_E6_AD_A5_E5_A4_9A_E7_BA_BF_E7_A8_8B_E4_BB_BB_E5_8A_A1.png]: http://cdn.blog.shangwantong.com/java-core/thread/%E5%90%8C%E6%AD%A5%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%BB%BB%E5%8A%A1.png [E5_BC_82_E6_AD_A5_E5_A4_9A_E7_BA_BF_E7_A8_8B_E4_BB_BB_E5_8A_A1.png]: http://cdn.blog.shangwantong.com/java-core/thread/%E5%BC%82%E6%AD%A5%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%BB%BB%E5%8A%A1.png
还没有评论,来说两句吧...