spring scope與線程之間的關(guān)系怎么解釋?有沒有什么關(guān)聯(lián)性?
問題如下:
spring scope 模擬為單例模式,則認為多次請求同一個地址時,是按順序執(zhí)行,如同時執(zhí)行 5次 a的test方法,會按順序執(zhí)行
如下代碼:
@GetMapping("test1")
public Object test1(HttpServletRequest request) throws InterruptedException {
logger.error("this:{},in time:{}", this.toString(), System.currentTimeMillis());
String sleepFlag = request.getParameter("sleep");
if ("on".equalsIgnoreCase(sleepFlag)) {
Thread.currentThread().sleep(10000l);
logger.error("return time:{}", System.currentTimeMillis());
return "sleep 10s";
}
logger.error("return time:{}", System.currentTimeMillis());
return "no sleep";
}
1. http://localhost:8080/test1?sleep=on
2. http://localhost:8080/test1
各執(zhí)行兩次,執(zhí)行順序為1-1、1-2、2-1、2-2,打印結(jié)果如下:
2018-03-26 16:56:03.793 ERROR 16292 --- [nio-8080-exec-1] c.e.m.web.controller.UserController : this:com.example.multimodule.web.controller.UserController@7f74f276,in time:1522054563793
2018-03-26 16:56:07.349 ERROR 16292 --- [nio-8080-exec-2] c.e.m.web.controller.UserController : this:com.example.multimodule.web.controller.UserController@7f74f276,in time:1522054567349
2018-03-26 16:56:07.349 ERROR 16292 --- [nio-8080-exec-2] c.e.m.web.controller.UserController : return time:1522054567349
2018-03-26 16:56:09.438 ERROR 16292 --- [nio-8080-exec-4] c.e.m.web.controller.UserController : this:com.example.multimodule.web.controller.UserController@7f74f276,in time:1522054569437
2018-03-26 16:56:09.438 ERROR 16292 --- [nio-8080-exec-4] c.e.m.web.controller.UserController : return time:1522054569438
2018-03-26 16:56:13.797 ERROR 16292 --- [nio-8080-exec-1] c.e.m.web.controller.UserController : return time:1522054573797
2018-03-26 16:56:13.801 ERROR 16292 --- [nio-8080-exec-8] c.e.m.web.controller.UserController : this:com.example.multimodule.web.controller.UserController@7f74f276,in time:1522054573801
2018-03-26 16:56:23.801 ERROR 16292 --- [nio-8080-exec-8] c.e.m.web.controller.UserController : return time:1522054583801
結(jié)果: 執(zhí)行過程中 1-1與1-2符合預期結(jié)果,即第一次執(zhí)行完成以后休眠10s執(zhí)行第二次,但1-1與2-1中間并沒有休眠過程(有時間差是因為手工執(zhí)行的),并且不管controller是否設(shè)置為scope=prototype,執(zhí)行結(jié)果都是一樣的
求解釋
按照你所說,在controller 中執(zhí)行休眠的時候,符合差不多同時執(zhí)行的規(guī)律
但是如果在controller 調(diào)用service,service執(zhí)行休眠的時候,兩個間隔時間比較長,但又小于休眠時間,具體代碼如下
@RestController
@RequestMapping("/test")
public class TestController {
private static final Logger logger = LoggerFactory.getLogger(TestController.class);
@Autowired
private IUserService userService;
@GetMapping("/user")
public Object testUser() {
logger.info("testController:{}", this.toString());
logger.info("userService:{}", userService.toString());
userService.get(1l);
return "ok";
}
@RequestMapping("/foo2")
public Object foo2(HttpServletRequest request) throws InterruptedException {
String param = request.getParameter("p");
logger.error("param:{}", param);
long start = System.currentTimeMillis();
Thread.sleep(10000);
long end = System.currentTimeMillis();
logger.error("time:{}", end - start);
return end - start;
}
}
@Override
public void get(Long id) {
logger.error("get start...{}", this.toString());
try {
Thread.sleep(30000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.error("get end...{}", this.toString());
}
結(jié)果如下:
2018-03-28 15:53:04.559 INFO 21776 --- [io-8080-exec-10] c.e.m.web.controller.TestController : testController:com.example.multimodule.web.controller.TestController@189ebbd
2018-03-28 15:53:04.559 INFO 21776 --- [io-8080-exec-10] c.e.m.web.controller.TestController : userService:com.example.multimodule.service.service.impl.UserServiceImpl@2a12ba65
2018-03-28 15:53:04.559 ERROR 21776 --- [io-8080-exec-10] c.e.m.s.service.impl.UserServiceImpl : get start...com.example.multimodule.service.service.impl.UserServiceImpl@2a12ba65
2018-03-28 15:53:25.665 INFO 21776 --- [nio-8080-exec-4] c.e.m.web.controller.TestController : testController:com.example.multimodule.web.controller.TestController@189ebbd
2018-03-28 15:53:25.665 INFO 21776 --- [nio-8080-exec-4] c.e.m.web.controller.TestController : userService:com.example.multimodule.service.service.impl.UserServiceImpl@2a12ba65
2018-03-28 15:53:25.665 ERROR 21776 --- [nio-8080-exec-4] c.e.m.s.service.impl.UserServiceImpl : get start...com.example.multimodule.service.service.impl.UserServiceImpl@2a12ba65
2018-03-28 15:53:34.559 ERROR 21776 --- [io-8080-exec-10] c.e.m.s.service.impl.UserServiceImpl : get end...com.example.multimodule.service.service.impl.UserServiceImpl@2a12ba65
2018-03-28 15:53:55.665 ERROR 21776 --- [nio-8080-exec-4] c.e.m.s.service.impl.UserServiceImpl : get end...com.example.multimodule.service.service.impl.UserServiceImpl@2a12ba65
2018-03-28 15:54:01.853 ERROR 21776 --- [nio-8080-exec-8] c.e.m.web.controller.TestController : param:aaaaa
2018-03-28 15:54:03.788 ERROR 21776 --- [nio-8080-exec-5] c.e.m.web.controller.TestController : param:bbbb
2018-03-28 15:54:11.854 ERROR 21776 --- [nio-8080-exec-8] c.e.m.web.controller.TestController : time:10000
2018-03-28 15:54:13.788 ERROR 21776 --- [nio-8080-exec-5] c.e.m.web.controller.TestController : time:10000
可以看到兩次執(zhí)行foo2請求,基本是同時執(zhí)行,但兩次執(zhí)行user,中間間隔時間較長
我個人認為是你把單例和線程安全搞混了,單例并不意味著線程安全,多線程同時訪問單例同樣存在并發(fā)問題,除非你手動加鎖。下面通過一個例子說明,你覺得最后 count 會是多少?
public class Demo {
private int count;
public void add() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.count++;
}
public static void main(String[] args) {
Demo d = new Demo();
// 8個線程同時訪問同一個 demo
new Thread(() -> {d.add();}).start();
new Thread(() -> {d.add();}).start();
new Thread(() -> {d.add();}).start();
new Thread(() -> {d.add();}).start();
new Thread(() -> {d.add();}).start();
new Thread(() -> {d.add();}).start();
new Thread(() -> {d.add();}).start();
new Thread(() -> {d.add();}).start();
// 主線程休眠 2 s ,等其他線程執(zhí)行結(jié)束
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(d.count);
}
}
北大青鳥APTECH成立于1999年。依托北京大學優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
北大青鳥中博軟件學院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網(wǎng)學院和江蘇省首批服務(wù)外包人才培訓基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團創(chuàng)建于1999年,經(jīng)過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術(shù)與教育服務(wù)機構(gòu),發(fā)展為教育服務(wù)業(yè)的綜合性企業(yè)集團,成為集合面授教學培訓、網(wǎng)
達內(nèi)教育集團成立于2002年,是一家由留學海歸創(chuàng)辦的高端職業(yè)教育培訓機構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
曾工作于聯(lián)想擔任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔任項目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍懿科技有限責任公司從事總經(jīng)理職務(wù)負責iOS教學及管理工作。
浪潮集團項目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗,技術(shù)功底深厚。 授課風格 授課風格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。