controller是线程不安全的,因为controller使用的是单例模式,不同的线程会对数据进行共享,导致数据混乱,没有实现我们想要的结果,除非定义的是常量,那就没有关系.
因为设计成单例模式的话,就不需要处理太多的gc,性能就可能得到提高
@RestController @RequestMapping("notSafe") public class ControllerNotSafeTest { //1、定义num,判断不同线程访问的时候,num的返回结果是否一致 private Integer num=0; /** * 2、定义两个方法 */ @GetMapping("/test1") public Integer test1(){ System.out.println(++num); return num; } @GetMapping("/test2") public Integer test2(){ System.out.println(++num); return num; } }
依次调用test1和test2方法
测试结果:发现结果是在test1的结果下进行叠加的
1 2
那么如果想让controller变成线程安全,也就是每个线程独享自己的属性,应该怎么处理呢?
方式一:使用多例模式
增加注解:@Scope("prototype")
@RestController @RequestMapping("notSafe") public class ControllerNotSafeTest { //1、定义num,判断不同线程访问的时候,num的返回结果是否一致 private Integer num=0; /** * 2、定义两个方法 */ @GetMapping("/test1") public Integer test1(){ System.out.println(++num); return num; } @GetMapping("/test2") public Integer test2(){ System.out.println(++num); return num; } }
方式二:使用threadLocal进行数据的处理
@RestController //修改为多例模式 @Scope("prototype") @RequestMapping("threadLocalSafe") public class ControllerSafeThreadLocalTest { //1、定义threadLocal 线程独享 ThreadLocal<Integer> threadLocal=new ThreadLocal<>(); /** * 2、定义两个方法 */ @GetMapping("/test1") public void test1(){ threadLocal.set(1); System.out.println(threadLocal.get()); } @GetMapping("/test2") public void test2(){ threadLocal.set(2); System.out.println(threadLocal.get()); } }
执行结果:test1和test2线程可以操纵自己的threadLocal,从而达到数据隔离
1 2