threadlocal用法示例,threadlocal使用场景

首页 > 技术 > 作者:YD1662023-04-15 23:54:10

出现问题的原因

threadlocal用法示例,threadlocal使用场景(5)

多个线程的task指向了同一个SimpleDateFormat对象,SimpleDateFormat是非线程安全的。

解决问题的方案

格式化代码是在最后一句return dateFormat.format(date);,所以可以为最后一句代码添加synchronized锁

public String date(int seconds) { //参数的单位是毫秒,从1970.1.1 00:00:00 GMT 开始计时 Date date = new Date(1000 * seconds); String s; synchronized (ThreadLocalNormalUsage04.class) { s = dateFormat.format(date); } return s; }

运行结果

threadlocal用法示例,threadlocal使用场景(6)

运行结果中没有发现相同的时间,达到了线程安全的目的

缺点:因为添加了synchronized,所以会保证同一时间只有一条线程可以执行,这在高并发场景下肯定不是一个好的选择,所以看看其他方案吧。

/** * 利用 ThreadLocal 给每个线程分配自己的 dateFormat 对象 * 不但保证了线程安全,还高效的利用了内存 */ public class ThreadLocalNormalUsage05 { public static ExecutorService threadPool = Executors.newFixedThreadPool(10); public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 1000; i ) { int finalI = i; //提交任务 threadPool.submit(new Runnable() { @Override public void run() { String date = new ThreadLocalNormalUsage05().date(finalI); System.out.println(date); } }); } threadPool.shutdown(); } public String date(int seconds) { //参数的单位是毫秒,从1970.1.1 00:00:00 GMT 开始计时 Date date = new Date(1000 * seconds); //获取 SimpleDateFormat 对象 SimpleDateFormat dateFormat = ThreadSafeFormatter.dateFormatThreadLocal.get(); return dateFormat.format(date); } } class ThreadSafeFormatter { public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>(){ //创建一份 SimpleDateFormat 对象 @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); } }; }

运行结果

threadlocal用法示例,threadlocal使用场景(7)

使用了ThreadLocal后不同的线程不会有共享的 SimpleDateFormat 对象,所以也就不会有线程安全问题

2.2 实践场景2

当前用户信息需要被线程内的所有方法共享

threadlocal用法示例,threadlocal使用场景(8)

上一页1234下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.