• 多线程 实现高效多借口调用


    正常情况下我们调用多借口,都会顺序调用,也就是串行,如果借口直接没有任何关系,而串行执行消耗的时间,就是各个借口直接调用的总和。而jdk其实给我们提供有返回值类型线程,可以解决这个问题。

    测试基类:用于统计执行时间

    import org.apache.commons.lang.StringUtils;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Rule;
    import org.junit.rules.TestName;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import com.ms.cloud.common.util.frame.SpObserver;
    
    @RunWith(SpringRunner.class)
    public class BaseTest {
    
        
        private Long starttime;
        @Rule
        public TestName junitClass= new TestName();
        @Before
        public void before() {
            starttime = System.currentTimeMillis();
            setDataSource();
            System.out.println(junitClass.getMethodName() + "....................start....................");
        }
        @After
        public void after() {
            double usedtime = (System.currentTimeMillis() - starttime) / 1000.0;
            System.out.println("耗时  " + usedtime + " ms");
            System.out.println(junitClass.getMethodName() + "....................end....................");
        }
    
        protected void setDataSource() {
            this.setDataSource(null, null);
        }
        protected void setDataSource(String city, String sourceType) {
            if (StringUtils.isEmpty(city)) {
                city = "sz";
            }
            if (StringUtils.isEmpty(sourceType)) {
                sourceType = "PC";
            }
            SpObserver.putSoruce(sourceType);
            SpObserver.putSp(city);
        }
        
    }

    工具类,模拟用户调用多借口。每个接口消耗几秒钟。。

    import java.util.concurrent.TimeUnit;
    
    public class UserUtils {
    
        public static String getHead(String uid) throws InterruptedException {
            TimeUnit.SECONDS.sleep(2);
            return ""+uid+"】的头";
        }
        public static String getFace(String uid)throws InterruptedException {
            TimeUnit.SECONDS.sleep(5);
            return ""+uid+"】的脸";
        }
        public static String getFoot(String uid) throws InterruptedException {
            TimeUnit.SECONDS.sleep(7);
            return ""+uid+"】的脚";
        }
    }

    正常情况下我们执行程序如此:

    普通人:

    import org.junit.Test;
    
    public class MyGodTest extends BaseTest {
    
        @Test
        public void testDo() throws InterruptedException {
            String uid = "路人甲";
            StringBuffer sb = new StringBuffer();
            sb.append(UserUtils.getHead(uid)).append("
    ");
            sb.append(UserUtils.getFace(uid)).append("
    ");
            sb.append(UserUtils.getFoot(uid)).append("
    ");
            System.out.println("信息为:
    " + sb.toString());
        }
    }

    直接串联:执行结果耗时14+s

    testDo....................start....................
    信息为:
    【路人甲】的头
    【路人甲】的脸
    【路人甲】的脚

    耗时 14.016 ms testDo....................end....................

    老程序员:

    开启多线程,异步模式。用线程池与不用都可以。。让线程跑起来就行

    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.FutureTask;
    
    import org.junit.Test;
    
    /**
     * @desc 采用线程方式 
     * @author 陈惟鲜 chenweixian
     * @date 2020年7月23日 下午1:00:23
     *
     */
    public class MyGodThreadTest extends BaseTest {
    
        /**用线程执行
         * @throws InterruptedException
         * @throws ExecutionException
         */
        @Test
        public void testDo() throws InterruptedException, ExecutionException {
            String uid = "路人甲";
            StringBuffer sb = new StringBuffer();
            Callable<String> headCallable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return UserUtils.getHead(uid);
                }
            };
            
            Callable<String> faceCallable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return UserUtils.getFace(uid);
                }
            };
            
            Callable<String> footCallable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return UserUtils.getFoot(uid);
                }
            };
            // 
            FutureTask<String> headFutureTask = new FutureTask<>(headCallable);
            FutureTask<String> faceFutureTask = new FutureTask<>(faceCallable);
            FutureTask<String> footFutureTask = new FutureTask<>(footCallable);
            
            // 执行方法,线程异步执行
            new Thread(headFutureTask).start();
            new Thread(faceFutureTask).start();
            new Thread(footFutureTask).start();
            
            sb.append(headFutureTask.get()).append("
    ");
            sb.append(faceFutureTask.get()).append("
    ");
            sb.append(footFutureTask.get()).append("
    ");
            System.out.println("信息为:
    " + sb.toString());
        }
        
        /**用线程池执行
         * @throws InterruptedException
         * @throws ExecutionException
         */
        @Test
        public void testPoolDo() throws InterruptedException, ExecutionException {
            String uid = "路人甲";
            StringBuffer sb = new StringBuffer();
            Callable<String> headCallable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return UserUtils.getHead(uid);
                }
            };
            
            Callable<String> faceCallable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return UserUtils.getFace(uid);
                }
            };
            
            Callable<String> footCallable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return UserUtils.getFoot(uid);
                }
            };
            // 
            FutureTask<String> headFutureTask = new FutureTask<>(headCallable);
            FutureTask<String> faceFutureTask = new FutureTask<>(faceCallable);
            FutureTask<String> footFutureTask = new FutureTask<>(footCallable);
            
            // 执行方法,线程异步执行
            ExecutorService executor = Executors.newCachedThreadPool();
            executor.submit(headFutureTask);
            executor.submit(faceFutureTask);
            executor.submit(footFutureTask);
            executor.shutdown();
            
            sb.append(headFutureTask.get()).append("
    ");
            sb.append(faceFutureTask.get()).append("
    ");
            sb.append(footFutureTask.get()).append("
    ");
            System.out.println("线程池信息为:
    " + sb.toString());
        }
    }

    执行结果:7+s

    testPoolDo....................start....................
    线程池信息为:
    【路人甲】的头
    【路人甲】的脸
    【路人甲】的脚
    
    耗时  7.02 ms
    testPoolDo....................end....................

    总结:

    多学多看,多实践,对工作有帮助。

    核心部分如下

    Callable<String> footCallable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return UserUtils.getFoot(uid); == 业务处理
                }
            };
    FutureTask<String> headFutureTask = new FutureTask<>(headCallable);
    new Thread(faceFutureTask).start(); ==执行程序
    footFutureTask.get() ==得到响应结果
    
    


  • 相关阅读:
    java静态内部类的作用
    java CountDownLatch 控制异步和同步
    @PostConstruct注解
    Springboot bean初始化方法InitializingBean
    logback同时输出到控制台和文件,并按级别输出到不同的文件配置开箱即用
    记录一次Curator操作zookeeper的错误
    海豚调度DolphinScheduler源码分析(一)
    npm WARN config global `global`, `local` are deprecated. Use `location解决方法
    kafka单机环境搭建及其基本使用
    Ubuntu下使用国内源安装Docker
  • 原文地址:https://www.cnblogs.com/a393060727/p/13365813.html
Copyright © 2020-2023  润新知