你担忧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时候必定要注意。。。。  可是本次测试也只是在极限状况下,比较难发生。。。  可是也是有几率的

相关文章
相关标签/搜索