zoukankan      html  css  js  c++  java
  • 接口测试框架多线程并发线程不安全处理

    之前的接口是 Api,ApiModel,ApiHelper的形式。

    用ApiHelper专门处理api的数据加工,发送请求并获取返回。

    后来发现这种写法在单线程没问题,多线程并发下时,apiHelper处理数据会出现数据错乱。

    大致原因是apiHelper作为一个工具类,对api的所有操作都是static,就算sychronize之后,一些公用的值还是线程不安全,导致数据中途处理会串信息。

    我这边的解决办法直接把ApiHelper和Api合并了,合并后代码更简洁,一些数据的处理写起来更像流式数据的写法,而且线程控制更加安全。

    另:线上出现了一个SimpleDateFormat线程不安全的缺陷,之前一直没写demo,因为没用框架跑并发,这次并发加上了,顺便写了个demo,记录一下。

    package testdemo.junit5demo;
    
    import io.qameta.allure.Feature;
    import io.qameta.allure.Owner;
    import io.qameta.allure.Story;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.jupiter.api.RepeatedTest;
    import org.junit.jupiter.api.parallel.Execution;
    import org.junit.jupiter.api.parallel.ExecutionMode;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Date;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    //CorpStaffDataAnalyseServiceImpl
    //还有一个解决方案,手动加锁
    @Slf4j
    @Feature("SimpleDateFormat并发不安全示例")
    @Owner("zhzh.yin")
    public class ConcurrentTest {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        //StringBuffer是线程安全的,也就是多线程修改同一个StringBuffer对象的时候,过程是同步的,当然这就导致了StringBuffer的效率降低,毕竟如果要提升安全性,就必须要损失一定的效率。
        //synchronized
        //加锁
        private static final ThreadLocal<SimpleDateFormat> THREAD_LOCAL = new ThreadLocal<SimpleDateFormat>() {
            @Override
            protected SimpleDateFormat initialValue() {
                return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            }
        };
    //    @RepeatedTest(500)
        @Story("并发报错:simpleDateFormat线程不安全")
        @Execution(ExecutionMode.CONCURRENT)
        //解决方案:用DateTimeFormatter
        public void testFailure() throws ParseException, InterruptedException {
            String dateString = simpleDateFormat.format(new Date());
            log.info(dateString);
            Date time = simpleDateFormat.parse(dateString);
            String dateString2 = simpleDateFormat.format(time);
            assertEquals(dateString, dateString2);
        }
    //    @RepeatedTest(500)
        @Story("解决方案:局部变量")
        @Execution(ExecutionMode.CONCURRENT)
        //解决方案:局部变量
        public void testSuc2() throws ParseException, InterruptedException {
            SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = simpleDateFormat1.format(new Date());
            log.info(dateString);
            Date time = simpleDateFormat1.parse(dateString);
            String dateString2 = simpleDateFormat1.format(time);
            assertEquals(dateString, dateString2);
        }
    //    @RepeatedTest(500)
        @Story("解决方案:ThreadLocal")
        @Execution(ExecutionMode.CONCURRENT)
        //解决方案:使用ThreadLocal,每个线程都拥有自己的SimpleDateFormat对象副本。
        public void testSuc3() throws ParseException, InterruptedException {
            SimpleDateFormat simpleDateFormat2 = THREAD_LOCAL.get();
            if (simpleDateFormat2 == null) {
                simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            }String dateString = simpleDateFormat2.format(new Date());
            log.info(dateString);
            Date time = simpleDateFormat2.parse(dateString);
            String dateString2 = simpleDateFormat2.format(time);
            assertEquals(dateString, dateString2);
        }
    //    @RepeatedTest(500)
        @Story("解决方案:使用DateTimeFormatter")
        @Execution(ExecutionMode.CONCURRENT)
        public void testSuc1() throws ParseException, InterruptedException {
            String dateNow = LocalDateTime.now().format(dtf);
            String dateNow2=LocalDateTime.parse(dateNow,dtf).format(dtf);
            assertEquals(dateNow, dateNow2);
        }
    
    }
    

      

  • 相关阅读:
    Linux命令应用大词典-第11章 Shell编程
    Kubernetes 学习12 kubernetes 存储卷
    linux dd命令
    Kubernetes 学习11 kubernetes ingress及ingress controller
    Kubernetes 学习10 Service资源
    Kubernetes 学习9 Pod控制器
    Kubernetes 学习8 Pod控制器
    Kubernetes 学习7 Pod控制器应用进阶2
    Kubernetes 学习6 Pod控制器应用进阶
    Kubernetes 学习5 kubernetes资源清单定义入门
  • 原文地址:https://www.cnblogs.com/zhizhiyin/p/13426242.html
Copyright © 2011-2022 走看看