目录
写一个控制层的类
验证方法
编辑
分别执行如下请求,先执行等待时间久的
日志结果
结论
配置多例模式
配置文件application.properties
类加注解
配置类方式
增加验证 控制层 服务层 都是 singleton 模式情况 模拟线程不安全情况
service 代码
ctr
测试方式
运行日志
结论
加上prototype试下效果 线程安全
service
ctr
调用
日志
结论
写一个控制层的类
package com.example.ctr;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
@Slf4j
public class Api {
int cc = 0;
static int ccs = 0;
@RequestMapping("/sleep/{num}")
public String sleep(@PathVariable int num) throws InterruptedException {
cc = num;
ccs = num;
int s = num;
log.info(Thread.currentThread().getName()+" "+num+" start 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
Thread.sleep(num);
log.info(Thread.currentThread().getName()+" "+num+" end 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
return "ok 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs;
}
}
验证方法
分别执行如下请求,先执行等待时间久的
http://localhost:8101/api/sleep/60000
http://localhost:8101/api/sleep/30000
http://localhost:8101/api/sleep/10000
http://localhost:8101/api/sleep/5000
http://localhost:8101/api/sleep/1000
日志结果
2023-07-03 14:19:06.616 INFO 33444 --- [nio-8101-exec-1] com.example.ctr.Api : http-nio-8101-exec-1 60000 start 方法级变量=60000类级变量=60000 类级静态变量=60000
2023-07-03 14:19:07.171 INFO 33444 --- [nio-8101-exec-2] com.example.ctr.Api : http-nio-8101-exec-2 30000 start 方法级变量=30000类级变量=30000 类级静态变量=30000
2023-07-03 14:19:08.318 INFO 33444 --- [nio-8101-exec-3] com.example.ctr.Api : http-nio-8101-exec-3 10000 start 方法级变量=10000类级变量=10000 类级静态变量=10000
2023-07-03 14:19:09.705 INFO 33444 --- [nio-8101-exec-4] com.example.ctr.Api : http-nio-8101-exec-4 5000 start 方法级变量=5000类级变量=5000 类级静态变量=5000
2023-07-03 14:19:11.277 INFO 33444 --- [nio-8101-exec-5] com.example.ctr.Api : http-nio-8101-exec-5 1000 start 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-03 14:19:12.286 INFO 33444 --- [nio-8101-exec-5] com.example.ctr.Api : http-nio-8101-exec-5 1000 end 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-03 14:19:14.707 INFO 33444 --- [nio-8101-exec-4] com.example.ctr.Api : http-nio-8101-exec-4 5000 end 方法级变量=5000类级变量=1000 类级静态变量=1000
2023-07-03 14:19:18.322 INFO 33444 --- [nio-8101-exec-3] com.example.ctr.Api : http-nio-8101-exec-3 10000 end 方法级变量=10000类级变量=1000 类级静态变量=1000
2023-07-03 14:19:37.181 INFO 33444 --- [nio-8101-exec-2] com.example.ctr.Api : http-nio-8101-exec-2 30000 end 方法级变量=30000类级变量=1000 类级静态变量=1000
2023-07-03 14:20:06.628 INFO 33444 --- [nio-8101-exec-1] com.example.ctr.Api : http-nio-8101-exec-1 60000 end 方法级变量=60000类级变量=1000 类级静态变量=1000
可见 执行久的线程,在运行中 对象级的变量,再新请求来后变量发生改变
结论
方法级变量线程安全
对象级变量和静态变量都不安全
ok文章来源:https://www.toymoban.com/news/detail-517716.html
持续更新文章来源地址https://www.toymoban.com/news/detail-517716.html
配置多例模式
配置文件application.properties
spring.main.allow-bean-definition-overriding=true
类加注解
@Component
@Scope("prototype")
public class MyBean {
//...
}
配置类方式
@Configuration
public class MyConfig {
@Bean
@Scope("prototype")
public MyBean myBean(){
return new MyBean();
}
}
ok
持续更新
增加验证 控制层 服务层 都是 singleton 模式情况 模拟线程不安全情况
service 代码
package com.example.ctr;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class ApiServiceImpl {
int cc = 0;
static int ccs = 0;
public String sleep(int num) throws InterruptedException {
cc = num;
ccs = num;
int s = num;
log.info("service "+Thread.currentThread().getName()+" "+num+" start 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
Thread.sleep(num);
log.info("service "+Thread.currentThread().getName()+" "+num+" end 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
return "service "+"ok 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs;
}
}
ctr
package com.example.ctr;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/api")
@Slf4j
public class Api {
@Resource
private ApiServiceImpl apiServiceImpl;
int cc = 0;
static int ccs = 0;
@RequestMapping("/sleep/{num}")
public String sleep(@PathVariable int num) throws InterruptedException {
cc = num;
ccs = num;
int s = num;
log.info("ctr "+Thread.currentThread().getName()+" "+num+" start 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
Thread.sleep(num);
log.info("ctr "+Thread.currentThread().getName()+" "+num+" end 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
String res = apiServiceImpl.sleep(num);
return "ctr ok 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs+" "+res;
}
}
测试方式
http://localhost:8101/api/sleep/5000
http://localhost:8101/api/sleep/2000
http://localhost:8101/api/sleep/1000
运行日志
2023-07-04 09:55:34.827 INFO 21092 --- [io-8101-exec-10] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-10 10000 end 方法级变量=10000类级变量=10000 类级静态变量=10000
2023-07-04 09:55:42.148 INFO 21092 --- [nio-8101-exec-9] com.example.ctr.Api : ctr http-nio-8101-exec-9 30000 end 方法级变量=30000类级变量=1000 类级静态变量=1000
2023-07-04 09:55:42.148 INFO 21092 --- [nio-8101-exec-9] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-9 30000 start 方法级变量=30000类级变量=30000 类级静态变量=30000
2023-07-04 09:56:04.722 INFO 21092 --- [nio-8101-exec-7] com.example.ctr.Api : ctr http-nio-8101-exec-7 5000 start 方法级变量=5000类级变量=5000 类级静态变量=5000
2023-07-04 09:56:05.898 INFO 21092 --- [nio-8101-exec-6] com.example.ctr.Api : ctr http-nio-8101-exec-6 2000 start 方法级变量=2000类级变量=2000 类级静态变量=2000
2023-07-04 09:56:06.974 INFO 21092 --- [nio-8101-exec-1] com.example.ctr.Api : ctr http-nio-8101-exec-1 1000 start 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-04 09:56:07.902 INFO 21092 --- [nio-8101-exec-6] com.example.ctr.Api : ctr http-nio-8101-exec-6 2000 end 方法级变量=2000类级变量=1000 类级静态变量=1000
2023-07-04 09:56:07.902 INFO 21092 --- [nio-8101-exec-6] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-6 2000 start 方法级变量=2000类级变量=2000 类级静态变量=2000
2023-07-04 09:56:07.980 INFO 21092 --- [nio-8101-exec-1] com.example.ctr.Api : ctr http-nio-8101-exec-1 1000 end 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-04 09:56:07.980 INFO 21092 --- [nio-8101-exec-1] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-1 1000 start 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-04 09:56:08.988 INFO 21092 --- [nio-8101-exec-1] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-1 1000 end 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-04 09:56:09.736 INFO 21092 --- [nio-8101-exec-7] com.example.ctr.Api : ctr http-nio-8101-exec-7 5000 end 方法级变量=5000类级变量=1000 类级静态变量=1000
2023-07-04 09:56:09.736 INFO 21092 --- [nio-8101-exec-7] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-7 5000 start 方法级变量=5000类级变量=5000 类级静态变量=5000
2023-07-04 09:56:09.907 INFO 21092 --- [nio-8101-exec-6] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-6 2000 end 方法级变量=2000类级变量=5000 类级静态变量=5000
2023-07-04 09:56:12.161 INFO 21092 --- [nio-8101-exec-9] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-9 30000 end 方法级变量=30000类级变量=5000 类级静态变量=5000
2023-07-04 09:56:14.748 INFO 21092 --- [nio-8101-exec-7] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-7 5000 end 方法级变量=5000类级变量=5000 类级静态变量=5000
结论
只要是对象层的变量在并发情况下会出现线程不安全情况
方法层值是安全情况
ok
持续更新
加上prototype试下效果 线程安全
service
package com.example.ctr;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@Scope("prototype")
public class ApiServiceImpl {
int cc = 0;
static int ccs = 0;
public String sleep(int num) throws InterruptedException {
cc = num;
ccs = num;
int s = num;
log.info("service "+Thread.currentThread().getName()+" "+num+" start 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
Thread.sleep(num);
log.info("service "+Thread.currentThread().getName()+" "+num+" end 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
return "service "+"ok 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs;
}
}
ctr
package com.example.ctr;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/api")
@Slf4j
@Scope("prototype")
public class Api {
@Resource
private ApiServiceImpl apiServiceImpl;
int cc = 0;
static int ccs = 0;
@RequestMapping("/sleep/{num}")
public String sleep(@PathVariable int num) throws InterruptedException {
cc = num;
ccs = num;
int s = num;
log.info("ctr "+Thread.currentThread().getName()+" "+num+" start 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
Thread.sleep(num);
log.info("ctr "+Thread.currentThread().getName()+" "+num+" end 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs);
String res = apiServiceImpl.sleep(num);
return "ctr ok 方法级变量="+s+"类级变量=" +cc +" 类级静态变量="+ccs+" "+res;
}
}
调用
同上方一样
日志
2023-07-04 10:05:51.245 INFO 34548 --- [nio-8101-exec-2] com.example.ctr.Api : ctr http-nio-8101-exec-2 5000 start 方法级变量=5000类级变量=5000 类级静态变量=5000
2023-07-04 10:05:51.683 INFO 34548 --- [nio-8101-exec-1] com.example.ctr.Api : ctr http-nio-8101-exec-1 2000 start 方法级变量=2000类级变量=2000 类级静态变量=2000
2023-07-04 10:05:52.842 INFO 34548 --- [nio-8101-exec-3] com.example.ctr.Api : ctr http-nio-8101-exec-3 1000 start 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-04 10:05:53.696 INFO 34548 --- [nio-8101-exec-1] com.example.ctr.Api : ctr http-nio-8101-exec-1 2000 end 方法级变量=2000类级变量=2000 类级静态变量=1000
2023-07-04 10:05:53.696 INFO 34548 --- [nio-8101-exec-1] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-1 2000 start 方法级变量=2000类级变量=2000 类级静态变量=2000
2023-07-04 10:05:53.851 INFO 34548 --- [nio-8101-exec-3] com.example.ctr.Api : ctr http-nio-8101-exec-3 1000 end 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-04 10:05:53.851 INFO 34548 --- [nio-8101-exec-3] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-3 1000 start 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-04 10:05:54.858 INFO 34548 --- [nio-8101-exec-3] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-3 1000 end 方法级变量=1000类级变量=1000 类级静态变量=1000
2023-07-04 10:05:55.698 INFO 34548 --- [nio-8101-exec-1] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-1 2000 end 方法级变量=2000类级变量=2000 类级静态变量=1000
2023-07-04 10:05:56.259 INFO 34548 --- [nio-8101-exec-2] com.example.ctr.Api : ctr http-nio-8101-exec-2 5000 end 方法级变量=5000类级变量=5000 类级静态变量=1000
2023-07-04 10:05:56.259 INFO 34548 --- [nio-8101-exec-2] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-2 5000 start 方法级变量=5000类级变量=5000 类级静态变量=5000
2023-07-04 10:06:01.268 INFO 34548 --- [nio-8101-exec-2] com.example.ctr.ApiServiceImpl : service http-nio-8101-exec-2 5000 end 方法级变量=5000类级变量=5000 类级静态变量=5000
结论
加上prototype 线程安全 每次调用bean 创建对象
类级变量是线程安全的
ok
持续更新
到了这里,关于Springboot tomcat bean 默认作用域 singleton 情况下模拟线程不安全情况 设置多例方式 prototype的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!