SimpleDateFormat多线程天坑

问题背景

在公司开发统计数据类项目的时候,遇到一个统计接口需要请求3万次数据库,单线程执行实在是太慢,每次都需要好几分钟的时间,所以便想着使用多线程来提高一下执行速度。
这个项目是一个电力统计系统,发电厂分为火力发电厂,水力发电厂和新能源发电厂,该接口需要汇总的是:每个月—每种类型的发电厂所发电量。
例如:一月份:火力发电厂发了20万千瓦时,水力发电厂发了10万千瓦时,新能源发电厂发了5万千瓦时。

问题重现

同一个SimpleDateFormat实例使用在多线程中出现的问题(本例子是打印从当前时间开始以及往后的12个月份的年月信息)

public static Date addMonth(Date date,int num) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MONTH,date.getMonth() + num);
        return calendar.getTime();
    }

    @Test
    public void test02() throws InterruptedException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
        Date nowDate = new Date();
        Calendar calendar = Calendar.getInstance();
        //多线程
        for (int i=0; i <=12; i++) {
            final int j = i;
            Date begDate = this.addMonth(nowDate,j);
            Thread thread01 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(dateFormat.format(begDate));
                }
            });
            thread01.start();
        }

        //非多线程
/*        for (int i=0; i <=12; i++) {
            final int j = i;
            Date begDate = TestThread.addMonth	(nowDate,j);
            System.out.println(dateFormat.format(begDate));
        }*/

        Thread.sleep(3000);

    }

多线程输出的其中一种错误结果:
在这里插入图片描述
在上面的图片中,本应该输出2021-04到2022-04的,但是因为在线程中使用了同一个实例的SimpleDateFormat,使得2021-04变成了2021-06,导致错误的结果。

改进

方法一:多线程部分将format操作移出线程:

		//多线程
        for (int i=0; i <=12; i++) {
            final int j = i;
            Date begDate = this.addMonth(nowDate,j);
            String formatDate = dateFormat.format(begDate);
            Thread thread01 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(formatDate);
                }
            });
            thread01.start();
        }

方法二:使用线程安全的DateTimeformatter类

    @Test
    public void test02() throws InterruptedException {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        LocalDate nowDate = LocalDate.now();

        //线程安全多线程
        for (int i=0; i <=12; i++) {
            final int j = i;
            LocalDate begDate = nowDate.plusMonths(j);
            Thread thread01 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(formatter.format(begDate));
                }
            });
            thread01.start();
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值