本帖最后由 唐三是反派 于 2023-3-23 11:00 编辑
一、自我介绍hello!大家好,本人是一名Java程序员,热爱生活、热爱学习、希望能在多御结实志同道合的猿类。
二、新年计划22年已去,23年已至。看到圈内很多优秀的大佬在开工第一天就开始制定自己全年的计划了,果然越优秀的人越努力。以前都是随着项目用到什么技术才去学习使用,但仅仅是使用还不是深入去理解。给我的感觉是我始终在原地踏步或是龟速前进。所以今年开始尝试改变自己,先从年度计划开始入手,为了防止计划制定有偏差,我先从半年计划开始制定,这样即使有偏差也不会偏的太狠。 - 2月:学习K8S、Jenkins相关构建流程、学会编写基本Shell脚本
- 3月~4月:学习计算机网络原理
- 5月:初步了解JVM
- 6月:学会基础Linux操作命令和理论知识
三、技术分享今日想跟大家分享的是ThreadLocal这个类,平时在使用多线程的时候我们最担心的是对象的线程安全问题。好在JDK提供了ThreadLocal这个类。从名字上看这是一个线程的局部变量。也就是说,只有当前线程可以访问。可想而知那自然是线程安全的。 ThreadLocal的简单使用- public class ThreadLocalTest {
-
- private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- public static class ParseDate implements Runnable {
-
- int i = 0;
- public ParseDate(int i) {
- this.i = i;
- }
- public void run() {
- try {
- Date t = sdf.parse("2023-02-06 17:29:29");
- System.out.println(i + "---->" + t);
- } catch (ParseException e) {
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- ExecutorService es = Executors.newFixedThreadPool(10);
- for (int i = 0; i < 1000; i++) {
- es.execute(new ParseDate(i));
- }
- }
- }
复制代码上面这段代码在多线程环境中运行有可能会出现异常,因为SimpleDateFormat.parse()方法并不是线程安全的。要想不出错,一种方案是在sdf.parse()方法前后加锁,另一种则是用ThreadLocal为每一个线程创建一个SimpleDateFormat,我们稍微改动一下代码
- public class ThreadLocalTest {
- private static Thread SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- public static class ParseDate implements Runnable {
- int i = 0;
- public ParseDate(int i) {
- this.i = i;
- }
- public void run() {
- try {
- if (tl.get()==null){
- tl.set(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
- }
- Date t = tl.get().parse("2023-02-06 17:29:29");
- System.out.println(i + "---->" + t);
- } catch (ParseException e) {
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- ExecutorService es = Executors.newFixedThreadPool(10);
- for (int i = 0; i < 1000; i++) {
- es.execute(new ParseDate(i));
- }
- }
- }
复制代码 ThreadLocal实现原理ThreadLocal是如何保证这些对象只被当前线程访问的呢?我们深入ThreadLocal的源码,主要关注set()和get()方法,先看set()方法:
|