博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
日期工具:非线程安全SimpleDateFormat 和线程安全JodaTime(推荐)
阅读量:4219 次
发布时间:2019-05-26

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

1、SimpleDateFormat不是线程安全的对象

举个栗子:

@Slf4jpublic class DateFormatExample1 {        private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");    //  请求总数    public static int clientTotal = 5000;    // 同时并发执行的线程数    public static int threadTotal = 200;    public static StringBuffer stringBuffer = new StringBuffer();    public static void main(String[] args) throws InterruptedException {        ExecutorService executorService = Executors.newCachedThreadPool();        final Semaphore semaphore = new Semaphore(threadTotal);        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);        for (int i = 0; i< clientTotal; i ++) {            executorService.execute(()->{                try {                    semaphore.acquire();                    update();                    semaphore.release();                } catch (InterruptedException e) {                    e.printStackTrace();                }                countDownLatch.countDown();            });        }        countDownLatch.await();        executorService.shutdown();    }    public static void update() {        try {            simpleDateFormat.parse("20180208");        } catch (ParseException e) {            log.error("parse exception", e);        }    }    }
输出:
at java.lang.Thread.run(Thread.java:748)
java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1890)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at java.text.DigitList.getDouble(DigitList.java:169)
at java.text.DecimalFormat.parse(DecimalFormat.java:2056)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1867)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at com.example.concurrent.commonUnsafe.DateFormatExample1.update(DateFormatExample1.java:47)
at com.example.concurrent.commonUnsafe.DateFormatExample1.lambda$main$0(DateFormatExample1.java:33)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
2、改进上述SimpleDateFormat的用法(变为线程安全的)
改为局部变量(因为局部变量是堆栈封闭,线程安全的)每次声明一个新的变量来使用。
如下:
@Slf4jpublic class DateFormatExample2 {        //  请求总数    public static int clientTotal = 5000;    // 同时并发执行的线程数    public static int threadTotal = 200;    public static StringBuffer stringBuffer = new StringBuffer();    public static void main(String[] args) throws InterruptedException {        ExecutorService executorService = Executors.newCachedThreadPool();        final Semaphore semaphore = new Semaphore(threadTotal);        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);        for (int i = 0; i< clientTotal; i ++) {            executorService.execute(()->{                try {                    semaphore.acquire();                    update();                    semaphore.release();                } catch (InterruptedException e) {                    e.printStackTrace();                }                countDownLatch.countDown();            });        }        countDownLatch.await();        executorService.shutdown();    }    public static void update() {        try {            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");            simpleDateFormat.parse("20180208");        } catch (ParseException e) {            log.error("parse exception", e);        }    }}
3、利用JodaTime(线程安全的) (
推荐用这个,不关是因为线程安全的
如下:
@Slf4jpublic class DateFormatExample3 {    //  请求总数    public static int clientTotal = 5000;    // 同时并发执行的线程数    public static int threadTotal = 200;    private static DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyyMMdd");    public static void main(String[] args) throws InterruptedException {        ExecutorService executorService = Executors.newCachedThreadPool();        final Semaphore semaphore = new Semaphore(threadTotal);        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);        for (int i = 0; i< clientTotal; i ++) {            final int count = i;            executorService.execute(()->{                try {                    semaphore.acquire();                    update(count);                    semaphore.release();                } catch (InterruptedException e) {                    e.printStackTrace();                }                countDownLatch.countDown();            });        }        countDownLatch.await();        executorService.shutdown();    }    public static void update(int i) {        log.info("{},{}", i, DateTime.parse("20180208").toDate());    }}

转载地址:http://ogomi.baihongyu.com/

你可能感兴趣的文章
VBox fdisk 不显示 添加的硬盘 解决方法
查看>>
Secure CRT 自动记录日志 配置 小记
查看>>
RMAN RAC 到 单实例 duplicate 自动分配通道 触发 ORA-19505 错误
查看>>
mysql 随机分页的优化
查看>>
DB2快速创建测试库
查看>>
利用db2look查看ddl
查看>>
SD卡驱动分析--基于高通平台
查看>>
[图文] Seata AT 模式分布式事务源码分析
查看>>
pm 源码分析
查看>>
Sending the User to Another App
查看>>
kmsg_dump
查看>>
Getting a Result from an Activity
查看>>
Allowing Other Apps to Start Your Activity
查看>>
dev/mem
查看>>
pfn_valid 源码分析
查看>>
dev/kmem 和dev/mem的区别
查看>>
test-definitions/blob/master/auto-test/bigdata/bigdata.sh
查看>>
/test-definitions/blob/master/auto-test/blktrace/blktrace.sh
查看>>
test-definitions/blob/master/auto-test/blogbench/blogbench.sh
查看>>
test-definitions/blob/master/auto-test/boost/boost.sh
查看>>