你担心spring容器中scope为prototype的bean太大内存溢出吗?

提出假设

之前一直担心spring的scope为prototype的bean在一些高并发的场景下,吃不消吗,甚至会内存溢出,这样的担心不是没有道理的,(以下是假设因为这个类型的bean每一次都会产生新的实例,如果每个实例做一些时间比较长的任务,然后它会在这段时间常驻内存。那么它会爆炸吗?*

猜想1. 非并发的场景下,是正常的。因为它执行完之后在内存回收的时候总是可以被回收的

猜想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;

    private static int _100M = 100 * 1024 * 1024;

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

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

    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+"");
    }

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时候一定要注意。。。。
但是本次测试也只是在极限情况下,比较难发生。。。
但是也是有概率的

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值