你擔憂spring容器中scope爲prototype的bean太大內存溢出嗎?

出假設
以前一直擔憂spring的scope爲prototype的bean在一些高併發的場景下,吃不消嗎,甚至會內存溢出,這樣的擔憂不是沒有道理的,(如下是假設)由於這個類型的bean每一次都會產生新的實例,若是每一個實例作一些時間比較長的任務,而後它會在這段時間常駐內存。那麼它會爆炸嗎?*java

猜測1. 非併發的場景下,是正常的。由於它執行完以後在內存回收的時候老是能夠被回收的spring

猜測2.高併發的場景下,會內存溢出。由於在這段執行任務的期間,有多個Bean被初始化了,內存會不斷增長。併發

驗證猜測1
下面咱們大膽測試如下高併發

測試程序 
UserLogic.java測試

@Component
// 保證singleton每次調用userLogic的時候都是最新的userLogic,
// 若是沒有配合上面的使用,獲取這個bean的時候須要根據beanName獲取,beanName須要加上前綴scopedTarget
// 如getBean(scopedTarget.userLogic)
@org.springframework.context.annotation.Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserLogic {
    private Long timeMilis;spa

    private static int _100M = 100 * 1024 * 1024;.net

    private byte[] memory = new byte[_100M];prototype

    public UserLogic(){
        timeMilis = (new Date()).getTime();
    }debug

    public void printTime() {
        System.out.println(timeMilis+"");
    }內存

    public Long getTimeMilis() {
        return timeMilis;
    }

}

UserService.java

@Service
public class UserService {

    @Autowired
    UserLogic logic;

    public void printNowTime(){
        logic.printTime();
    }
}

Test.java

//TODO 查看如何建立scope註解的Logic的
            service = context.getBean("userService", UserService.class);
            logger.debug("===============================first================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(3);
            logger.debug("==============================second================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(3);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(3);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(3);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(3);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(3);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(5);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(5);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(5);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(5);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(5);

            logger.debug("=============================== end ================================");
            service.printNowTime();
            TimeUnit.SECONDS.sleep(5);

先測試下普通的,非高併發場景下的曲線 


能夠看到,被回收掉了,與預想的同樣

驗證猜測2
現修改UserLogic:::printTime()方法的代碼

public void printTime() throws InterruptedException {
        Thread.sleep(1000);
        System.out.println(timeMilis+"");
    }
1
2
3
4
ConcurrentTest.java

 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WuhulalaApplication.class);
        //context.start();
        final UserService service = context.getBean("userService", UserService.class);
        for (int i = 0; i < 20; i++) {
            new Thread(() ->{
                try {
                    service.printNowTime();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        while(true){}

果真報錯 
Caused by: java.lang.OutOfMemoryError: Java heap space

只不過這些bean執行完任務後立馬釋放了內存,因此曲線以下圖所示[直上直下]

總結 之後使用scope的prototype時候必定要注意。。。。  可是本次測試也只是在極限狀況下,比較難發生。。。  可是也是有機率的

相關文章
相關標籤/搜索