With the business development, the underlying data quantity is more and more big, the business logic is complicated, some interface is becoming more and more time consuming, interface is needed at this time performance optimization, performance optimization, of course, major related to business involves the transformation point may be different, here is to introduce an asynchronous call multiple interfaces to reduce response time

Suitable conditions

  • Multiple independent interfaces are invoked without interdependencies
  • The non-time-consuming interface accounts for a large proportion of the total time

Optimize the pre-call method

The code before optimization is called in order:

import lombok.extern.slf4j.Slf4j; @Slf4j public class DemoTest { public static void main(String[] args) throws Exception { long beginTime = System.currentTimeMillis(); int processA = new InterfaceA().process(); int processB = new InterfaceB().process(); int result = processA + processB; Log.info (" Execution result: {} Time: {}", result, system.currentTimemillis () -beginTime); } @Slf4j public final static class InterfaceA { Integer result = 1; public int process() { long beginTime = System.currentTimeMillis(); try { Thread.sleep(2000); } catch (Exception e) { log.error("InterfaceA.process Exception"); } log.info(" Interfacea.process time: {}ms", system.currentTimemillis () -beginTime); return result; } } @Slf4j public final static class InterfaceB { Integer result = 1; public int process() { long beginTime = System.currentTimeMillis(); try { Thread.sleep(2000); } catch (Exception e) { log.error("InterfaceB.process Exception"); } log.info(" Interfaceb.process time: {}ms", system.currentTimemillis () -beginTime); return result; }}}Copy the code

Execution Result:

21:40:17.603 [main] INFO DemoTest$InterfaceA 2002ms 21:40:19.612 [main] INFO DemoTest$InterfaceB 2001MS 21:40:19.613 [main] INFO DemoTest - Result: 2 Time: 4018Copy the code

Optimized invocation method

The optimized code is called asynchronously:

import cn.hutool.core.thread.ThreadFactoryBuilder; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @Slf4j public class DemoTest { private static ThreadPoolExecutor pool = new ThreadPoolExecutor( 5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000), ThreadFactoryBuilder. The create (). SetNamePrefix (" thread name - "). The build ()); public static void main(String[] args) throws Exception { long beginTime = System.currentTimeMillis(); List<Future<Integer>> futures = new ArrayList<>(2); List<Integer> results = new ArrayList<>(2); futures.add(pool.submit(() -> new InterfaceA().process())); futures.add(pool.submit(() -> new InterfaceB().process())); for (Future<Integer> item : futures) { results.add(item.get()); } int result = results.get(0) + results.get(1); Log.info (" Execution result: {} Time: {}", result, system.currentTimemillis () -beginTime); } @Slf4j public final static class InterfaceA { Integer result = 1; public int process() { long beginTime = System.currentTimeMillis(); try { Thread.sleep(2000); } catch (Exception e) { log.error("InterfaceA.process Exception"); } log.info(" Interfacea.process time: {}ms", system.currentTimemillis () -beginTime); return result; } } @Slf4j public final static class InterfaceB { Integer result = 1; public int process() { long beginTime = System.currentTimeMillis(); try { Thread.sleep(2000); } catch (Exception e) { log.error("InterfaceB.process Exception"); } log.info(" Interfaceb.process time: {}ms", system.currentTimemillis () -beginTime); return result; }}}Copy the code

Execution Result:

22:03:43.180 [thread name -1] INFO DemoTest$InterfaceB 2004ms 22:03:43.180 [thread name -0] INFO DemoTest$InterfaceA 2004ms 22:03:43.190 [main] INFO DemoTest - Result: 2 Time: 2020Copy the code

This approach can also be combined with CompletionService to separate asynchronous tasks from execution results so that people can search for their own practices

Powerful CompletableFuture JDK1.8

import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; @Slf4j public class DemoTest { public static void main(String[] args) throws Exception { long beginTime = System.currentTimeMillis(); CompletableFuture<Integer> interfaceFuturesA = CompletableFuture.supplyAsync(() -> new InterfaceA().process()); CompletableFuture<Integer> interfaceFuturesB = CompletableFuture.supplyAsync(() -> new InterfaceB().process()); CompletableFuture<List<Integer>> future = CompletableFuture .allOf(interfaceFuturesA, interfaceFuturesB) .thenApply((none) -> { List<Integer> dataList = new ArrayList<>(2); try { dataList.add(interfaceFuturesA.get()); dataList.add(interfaceFuturesB.get()); } catch (Exception e) {log.error(" execute Exception "); } return dataList; }).exceptionally(e -> Lists.newArrayList()); int result = future.get().get(0) + future.get().get(1); Log.info (" Execution result: {} Time: {}", result, system.currentTimemillis () -beginTime); } @Slf4j public final static class InterfaceA { Integer result = 1; public int process() { long beginTime = System.currentTimeMillis(); try { Thread.sleep(2000); } catch (Exception e) { log.error("InterfaceA.process Exception"); } log.info(" Interfacea.process time: {}ms", system.currentTimemillis () -beginTime); return result; } } @Slf4j public final static class InterfaceB { Integer result = 1; public int process() { long beginTime = System.currentTimeMillis(); try { Thread.sleep(2000); } catch (Exception e) { log.error("InterfaceB.process Exception"); } log.info(" Interfaceb.process time: {}ms", system.currentTimemillis () -beginTime); return result; }}}Copy the code

Execution Result:

22:31:44.822 [ForkJoinPool.com monpool-worker-5] INFO DemoTest$InterfaceB 2005ms 22:31:44.822 [ForkJoinPool.com monpool-worker-3] INFO DemoTest$InterfaceA 2002ms 22:31:44.831 [main] INFO DemoTest - Result: 2 Time: 2027Copy the code

Pay attention to optimization

  • Use thread pools to prevent memory overflow risks
  • The result container can be set as required
  • Interface granularity can be combined or split based on actual service conditions