ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【六】多线程 —— 共享模型之不可变

2021-08-03 14:59:41  阅读:144  来源: 互联网

标签:03 14 模型 1951 2021 共享 多线程 08 21


如果一个对象在不能够修改其内部状态(属性),那么它就是线程安全的,因为不存在并发修改。

比如类用 final 修饰保证了该类中的方法不能被覆盖,防止子类无意间破坏不可变性。

一、日期转换的问题

SimpleDateFormat 不是线程安全的,可能出现 java.lang.NumberFormatException 或者出现不正确的日期解析结果,例如:

public class SimpleDateFormatTest {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    ConsoleUtil.print(sdf.parse("1951-04-21").toString());
                } catch (Exception e) {
                    ConsoleUtil.print(e.toString());
                }
            }).start();
        }
    }
}
2021-08-03 14:34:55 Sat Jul 21 00:00:00 CST 1951
2021-08-03 14:34:55 java.lang.NumberFormatException: For input string: "19511951195119511951195119511951.EE441951195119511951195119511951195119511951E41951195119511951195119511951195119511E4"
2021-08-03 14:34:55 Mon Jul 21 00:00:00 CST 178958921
2021-08-03 14:34:55 Sat Jul 21 00:00:00 CST 1951
2021-08-03 14:34:55 java.lang.NumberFormatException: empty String
2021-08-03 14:34:55 java.lang.NumberFormatException: For input string: "19511951195119511951195119511951.EE441951195119511951195119511951195119511951E4"
2021-08-03 14:34:55 Sat Jul 21 00:00:00 CST 1951
2021-08-03 14:34:55 java.lang.NumberFormatException: multiple points
2021-08-03 14:34:55 java.lang.NumberFormatException: For input string: "19511951195119511951195119511951.EE441951195119511951195119511951195119511951"
2021-08-03 14:34:55 java.lang.NumberFormatException: multiple points

使用同步锁虽能解决问题,但带来的是性能上的损失,并不算很好, 加锁耗性能。

如果一个对象在不能够修改其内部状态(属性),因为不存在并发修改,那么它就是线程安全的,这样的对象在Java 中有很多,例如在 Java 8 后,提供了一个新的日期格式化类:

public class SimpleDateFormatTest01 {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    ConsoleUtil.print(dtf.parse("1951-04-21").toString());
                } catch (Exception e) {
                    ConsoleUtil.print(e.toString());
                }
            }).start();
        }
    }
}
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21
2021-08-03 14:38:16 {},ISO resolved to 1951-04-21

可以看 DateTimeFormatter 的文档:
在这里插入图片描述

二、final 的使用

IntegerDoubleStringDateTimeFormatterString以及基本类型包装类, 都是使用final来修饰的。

属性用 final 修饰保证了该属性是只读的,不能修改,类用 final 修饰保证了该类中的方法不能被覆盖,防止子类无意间破坏不可变性。

final原理

public class TestFinal {
	final int a = 20; 
}

字节码:

0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 20
7: putfield #2 // Field a:I
 <-- 写屏障
10: retu

final 变量的赋值通过 putfield 指令来完成,在这条指令之后会加入写屏障,保证在其它线程读到它的值时不会出现为 0 的情况。

标签:03,14,模型,1951,2021,共享,多线程,08,21
来源: https://blog.csdn.net/weixin_41231928/article/details/119349369

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有