鍍金池/ 問答/Linux  網(wǎng)絡(luò)安全/ spring scope與線程之間的關(guān)系?

spring scope與線程之間的關(guān)系?

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é)果都是一樣的

求解釋

回答
編輯回答
拮據(jù)

@oxf1992

按照你所說,在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,中間間隔時間較長

2017年4月5日 06:57
編輯回答
不將就

我個人認為是你把單例和線程安全搞混了,單例并不意味著線程安全,多線程同時訪問單例同樣存在并發(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);
    }
}
2018年6月23日 21:54