-
ThreadLocal是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问
-
ThreadLocal支持泛型,也就是支持value是可以设置类型的,像是
ThreadLocal<Date>
就是设置value为Date类型 -
每个线程会有自己的一份ThreadLocalMap变量,去储存这个线程自己想存放的ThreadLocal变量们,他内部储存的是一个键值对Map,其中key是某个ThreadLocal,value就是这个线程自己set的值,所以对于一个线程来说,一个ThreadLocal只能存一个值,而一个线程可以存放好多个ThreadLocal
-
因此当调用ThreadLocal
tl
的tl.get()
方法时,其实就是先去取得此线程的ThreadLocalMap,然后再去查找这个Map中的key为tl
的那个Entry的value值
-
-
ThreadLocal常用的方法
-
set(x)
: 设置此线程的想要放的值是多少 -
get()
: 取得此线程当初存放的值,如果没有存放过则返回null -
remove()
: 删除此线程的键值对,也就是如果先执行remove再执行get,会返回null
-
-
ThreadLocal通常用在SimpleDateFormat,或是SpringMVC上
-
因为SimpleDateFormat不是线程安全的,因此虽然可以每次要使用的时候重新
new
一个,但是这样做会很浪费资源,所以如果使用ThreadLocal在每个线程裡都存放一个此线程专用的SimpleDateFormat,就可以避免一直new
的资源浪费,又确保线程安全 -
因为SpringMVC会对每个请求分配一个线程,可以在拦截器将此线程的用户信息(ip、名字...)使用ThreadLocal储存,这样在后续要用到用户信息的地方时,就可以去ThreadLocal中取得,而且因为ThreadLocal可以隔离线程,因此每条请求对应的线程的用户信息不会互相干扰
-
-
具体实例
-
每个线程都可以在ThreadLocal中放自己的值,且不会干扰到其他线程的值
class Tools { public static ThreadLocal threadLocal = new ThreadLocal(); } class MyThread extends Thread { @Override public void run() { if (Tools.threadLocal.get() == null) { Tools.threadLocal.set(Thread.currentThread().getName() + ", " + Math.random()); } System.out.println(Tools.threadLocal.get()); } } public class Main { public static void main(String[] args) { for (int i = 0; i < 5; i++) { MyThread thread = new MyThread(); thread.setName("thread " + i); thread.start(); } } }
Tools { public static ThreadLocal threadLocal = new ThreadLocal(); } class MyThread extends Thread { @Override public void run() { if (Tools.threadLocal.get() == null) { Tools.threadLocal.set(Thread.currentThread().getName() + ", " + Math.random()); } System.out.println(Tools.threadLocal.get()); } } public class Main { public static void main(String[] args) { for (int i = 0; i < 5; i++) { MyThread thread = new MyThread(); thread.setName("thread " + i); thread.start(); } } }thread 1, 0.86 thread 0, 0.42 thread 2, 0.35 thread 3, 0.41 thread 4, 0.45
thread 0, 0.42 thread 2, 0.35 thread 3, 0.41 thread 4, 0.45 -
使用ThreadLocal在SimpleDateFormat上,并且给ThreadLocal加上泛型,指定value的类型是SimpleDateFormat
-
因为使用了ThreadLocal确保每个线程有自己一份SimpleDateFormat,所以线程安全,不会报错
class Tools { public static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>(); } class MyThread extends Thread { @Override public void run() { SimpleDateFormat sdf = Tools.threadLocal.get(); if (sdf == null) { sdf = new SimpleDateFormat("yyyy-MM-dd"); Tools.threadLocal.set(sdf); } try { System.out.println(sdf.parse("2018-07-15")); } catch (ParseException e) { System.out.println("报错了"); } } } public class Main { public static void main(String[] args) { for (int i = 0; i < 5; i++) { MyThread thread = new MyThread(); thread.setName("thread " + i); thread.start(); } } }
Tools { public static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>(); } class MyThread extends Thread { @Override public void run() { SimpleDateFormat sdf = Tools.threadLocal.get(); if (sdf == null) { sdf = new SimpleDateFormat("yyyy-MM-dd"); Tools.threadLocal.set(sdf); } try { System.out.println(sdf.parse("2018-07-15")); } catch (ParseException e) { System.out.println("报错了"); } } } public class Main { public static void main(String[] args) { for (int i = 0; i < 5; i++) { MyThread thread = new MyThread(); thread.setName("thread " + i); thread.start(); } } }Sun Jul 15 00:00:00 CST 2018 Sun Jul 15 00:00:00 CST 2018 Sun Jul 15 00:00:00 CST 2018 Sun Jul 15 00:00:00 CST 2018 Sun Jul 15 00:00:00 CST 2018
Sun Jul 15 00:00:00 CST 2018 Sun Jul 15 00:00:00 CST 2018 Sun Jul 15 00:00:00 CST 2018 Sun Jul 15 00:00:00 CST 2018 -
-
Java多线程 - ThreadLocal类的使用
最新推荐文章于 2023-01-30 18:41:38 发布