Immutable设计 & SimpleDateFormat & DateTimeFormatter

发布于:2025-02-10 ⋅ 阅读:(33) ⋅ 点赞:(0)

专栏系列文章地址:https://blog.csdn.net/qq_26437925/article/details/145290162

本文目标:

  1. 理解不可变设计模式,时间format有线程安全要求的注意使用DateTimeFormatter

Immutable

[ɪˈmjuːtəbl][ɪˈmjuːtəbl]
adj.
不变的;不可改变的;
例句
They free our minds from considering our world as fixed and immutable.
它们改变着人们将世界看作是永恒不变的观点。

在这里插入图片描述

SimpleDateFormat 非线程安全

例子代码

 static void test1(){
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    for (int i = 0; i < 10; i++) {
        new Thread(()->{
            try {
                Date date = dateFormat.parse("1999-09-09");
                System.out.println(date);
            }catch (Exception e){
                e.printStackTrace();
            }
        }).start();
    }
}

有线程会报错如下
在这里插入图片描述

可以synchronized解决,但效率低

static void test2(){
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    for (int i = 0; i < 10; i++) {
        new Thread(()->{
            synchronized (dateFormat) {
                try {
                    Date date = dateFormat.parse("1999-09-09");
                    System.out.println(date);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

DateTimeFormatter 线程安全

static void test3() {
   DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            try {
                LocalDateTime dateTime = LocalDateTime.parse("2023-01-01 12:00:00", dateTimeFormatter);
                System.out.println(dateTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }
}

线程安全原理

首先DateTimeFormatter是个final class, 这样所有线程都能使用它,不会有线程安全问题
在这里插入图片描述

另外:java.time.format.DateTimeFormatter#parseResolved0,也是将输入的format字符串也修饰成final的
在这里插入图片描述

其它不可变设计模式例子

Java String类为什么是final的?
  • value,offset和count这三个变量都是private的,并且没有提供setValue, setOffset和setCount等公共方法来修改这些值,所以在String类的外部无法修改String
  1. 为了实现字符串池

字符串池的实现可以在运行时节约很多heap空间,因为不同的字符串变量都指向池中的同一个字符串。但如果字符串是可变的,那么String intern将不能实现,因为这样的话,如果变量改变了它的值,那么其它指向这个值的变量的值也会一起改变

  1. 为了安全 & 线程安全

final不可变,确保线程安全

  1. 为了实现String可以创建HashCode不可变性,提高效率

因为字符串是不可变的,所以在它创建的时候HashCode就被缓存了,不需要重新计算。这就使得字符串很适合作为Map中的键,字符串的处理速度要快过其它的键对象。这就是HashMap中的键往往都使用字符串。

但也要注意到问题: 对象会创建的比较多,即占用内存会多


网站公告

今日签到

点亮在社区的每一天
去签到