博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SimpleDateFormat线程不安全原因及解决方案
阅读量:6311 次
发布时间:2019-06-22

本文共 4125 字,大约阅读时间需要 13 分钟。

线程不安全验证:

/** * SimpleDateFormat线程安全测试 * 〈功能详细描述〉 * * @author 17090889 * @see [相关类/方法](可选) * @since [产品/模块版本] (可选) */public class SimpleDateFormatTest {    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 100, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(1000), new MyThreadFactory("SimpleDateFormatTest"));    public void test() {        while (true) {            poolExecutor.execute(new Runnable() {                @Override                public void run() {                    String dateString = simpleDateFormat.format(new Date());                    try {                        Date parseDate = simpleDateFormat.parse(dateString);                        String dateString2 = simpleDateFormat.format(parseDate);                        System.out.println(dateString.equals(dateString2));                    } catch (ParseException e) {                        e.printStackTrace();                    }                }            });        }    }

输出:

true

false
true
true
false

出现了false,说明线程不安全

1、format方法

public StringBuffer format(Date date, StringBuffer toAppendTo,                               FieldPosition pos)    {        pos.beginIndex = pos.endIndex = 0;        return format(date, toAppendTo, pos.getFieldDelegate());    }    // Called from Format after creating a FieldDelegate    private StringBuffer format(Date date, StringBuffer toAppendTo,                                FieldDelegate delegate) {        // Convert input date to time field list        calendar.setTime(date);        boolean useDateFormatSymbols = useDateFormatSymbols();        for (int i = 0; i < compiledPattern.length; ) {            int tag = compiledPattern[i] >>> 8;            int count = compiledPattern[i++] & 0xff;            if (count == 255) {                count = compiledPattern[i++] << 16;                count |= compiledPattern[i++];            }            switch (tag) {            case TAG_QUOTE_ASCII_CHAR:                toAppendTo.append((char)count);                break;            case TAG_QUOTE_CHARS:                toAppendTo.append(compiledPattern, i, count);                i += count;                break;            default:                subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);                break;            }        }        return toAppendTo;    }
protected Calendar calendar;

可以看到,多个线程之间共享变量calendar,并修改calendar,因此在多线程环境下,线程是不安全的。

解决方案:

1、将SimpleDateFormat定义成局部变量

2、 加一把线程同步锁:synchronized(lock)

3、使用ThreadLocal,每个线程都拥有自己的SimpleDateFormat对象副本

  如:

/** * SimpleDateFormat线程安全测试 * 〈功能详细描述〉 * * @author 17090889 * @see [相关类/方法](可选) * @since [产品/模块版本] (可选) */public class SimpleDateFormatTest {    ThreadLocal
local = new ThreadLocal<>(); // private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 100, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(1000), new MyThreadFactory("SimpleDateFormatTest")); public void test() { while (true) { poolExecutor.execute(new Runnable() { @Override public void run() { SimpleDateFormat simpleDateFormat = local.get(); if (simpleDateFormat == null) { simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } String dateString = simpleDateFormat.format(new Date()); try { Date parseDate = simpleDateFormat.parse(dateString); String dateString2 = simpleDateFormat.format(parseDate); System.out.println(dateString.equals(dateString2)); } catch (ParseException e) { e.printStackTrace(); } finally { local.remove(); } } }); } }}

 

 

4、使用DateTimeFormatter代替SimpleDateFormat

 

转载于:https://www.cnblogs.com/yangyongjie/p/11017409.html

你可能感兴趣的文章
内存分布简视图
查看>>
POJ 2918 求解数独
查看>>
如何学习虚拟现实技术vr? vr初级入门教程开始
查看>>
第4 章序列的应用
查看>>
Mysql explain
查看>>
初识闭包
查看>>
java tcp socket实例
查看>>
011 指针的算术运算
查看>>
hdu1874畅通工程续
查看>>
rails 字符串 转化为 html
查看>>
java-学习8
查看>>
AOP动态代理
查看>>
Oracle序列
查看>>
xcodebuild命令行编译错误问题解决
查看>>
Yii2.0 下的 load() 方法的使用
查看>>
华为畅玩5 (CUN-AL00) 刷入第三方twrp Recovery 及 root
查看>>
LeetCode----67. Add Binary(java)
查看>>
母版页 MasterPage
查看>>
[转] ReactNative Animated动画详解
查看>>
DNS原理及其解析过程
查看>>