Controller是线程安全吗

controller是线程不安全的,因为controller使用的是单例模式,不同的线程会对数据进行共享,导致数据混乱,没有实现我们想要的结果,除非定义的是常量,那就没有关系.

因为设计成单例模式的话,就不需要处理太多的gc,性能就可能得到提高

@RestController
@RequestMapping("notSafe")
public class ControllerNotSafeTest {
    //1、定义num,判断不同线程访问的时候,num的返回结果是否一致
    private Integer num=0;

    /**
    * 2、定义两个方法
    */
    @GetMapping("/test")
    public Integer test(){
        System.out.println(++num);
ThreadUtil.sleep(1000000);
//可能在这里报错,导致上述操作回滚
return num; } }

测试结果:用test1test2线程访问,发现结果是在test1的结果下进行叠加的,当test1报错回滚后,test2依然在test1之前错误的结果上进行计算,所以有安全问题。

1
2

那么如果想让controller变成线程安全,也就是每个线程独享自己的属性,应该怎么处理呢?

方式一:使用多例模式

增加注解:@Scope("prototype")

@RestController
@RequestMapping("notSafe")
public class ControllerNotSafeTest {
    //1、定义num,判断不同线程访问的时候,num的返回结果是否一致
    private Integer num=0;

    /**
    * 2、定义两个方法
    */
    @GetMapping("/test")
    public Integer test(){
        System.out.println(++num);
ThreadUtil.sleep(1000000);
return num; } }

执行结果:用test1test2线程访问会产生多个实例,达到数据隔离

1
1

方式二:使用threadLocal进行数据的处理

@RestController
//修改为多例模式
@Scope("prototype")
@RequestMapping("threadLocalSafe")
public class ControllerSafeThreadLocalTest {
    //1、定义threadLocal 线程独享
    ThreadLocal<Integer> threadLocal=new ThreadLocal<>();

    /**
    * 2、定义两个方法
    */
    @GetMapping("/test")
    public void test(){
        threadLocal.set(1);
System.out.println(threadLocal.get());
threadLocal.set(2); ThreadUtil.sleep(1000000); }
}

执行结果:用test1test2线程访问可以操纵自己的threadLocal,从而达到数据隔离

1
1

 

posted @ 2022-06-01 17:39  yifanSJ  阅读(621)  评论(1编辑  收藏  举报