iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java中的ThreadLocal怎么用
  • 507
分享到

Java中的ThreadLocal怎么用

2023-06-17 06:06:18 507人浏览 八月长安
摘要

这篇文章给大家分享的是有关Java中的ThreadLocal怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。引言ThreadLocal的官方API解释为:“该类提供了线程局部 (thread-local) &

这篇文章给大家分享的是有关Java中的ThreadLocal怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

引言

ThreadLocal的官方API解释为:

“该类提供了线程局部 (thread-local)  变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副 本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务  ID)相关联。”

Java中的ThreadLocal怎么用

大概的意思有两点:

  1. ThreadLocal提供了一种访问某个变量的特殊方式:访问到的变量属于当前线程,即保证每个线程的变量不一样,而同一个线程在任何地方拿到的变量都是一致的,这就是所谓的线程隔离。

  2. 如果要使用ThreadLocal,通常定义为private static类型,在我看来***是定义为private static final类型。

应用场景

ThreadLocal通常用来共享数据,当你想在多个方法中使用某个变量,这个变量是当前线程的状态,其它线程不依赖这个变量,你***时间想到的 就是把变量定义在方法内部,然后再方法之间传递参数来使用,这个方法能解决问题,但是有个烦人的地方就是,每个方法都需要声明形参,多处声明,多处调用。 影响代码的美观和维护。有没有一种方法能将变量像private  static形式来访问呢?这样在类的任何一处地方就都能使用。这个时候ThreadLocal大显身手了。

实践

我们首先来看一段代码:

mport java.util.HashMap;  import java.util.Map;  public class TreadLocalTest {  // static ThreadLocal<HashMap> threadLocal = new ThreadLocal<HashMap>(){  // @Override  // protected HashMap initialValue() {  // System.out.println(Thread.currentThread().getName()+”initialValue”);  // return new HashMap();  // }  // };  public static class T1 implements Runnable {  private final static Map map = new HashMap();  int id;  public T1(int id) {  this.id = id;  }  public void run() {  // Map map = threadLocal.get();  for (int i = 0; i < 20; i++) {  map.put(i, i + id * 100);  try {  Thread.sleep(100);  } catch (Exception ex) {  }  }  System.out.println(Thread.currentThread().getName()  + “# map.size()=” + map.size() + ” # ” + map);  }  }  public static void main(String[] args) {  Thread[] runs = new Thread[15];  T1 t = new T1(1);  for (int i = 0; i < runs.length; i++) {  runs[i] = new Thread(t);  }  for (int i = 0; i < runs.length; i++) {  runs[i].start();  }  }  }

这段程序的本意是,启动15个线程,线程向map中写入20个整型值,然后输出map。运行该程序,观察结果,我们会发现,map中压根就不止20个元素,这说明程序产生了线程安全问题。

我们都知道HashMap是非线程安全的,程序启动了15个线程,他们共享了同一个map,15个线程都往map写对象,这势必引起线程安全问题。

我们有两种方法解决这个问题:

  1. 将map的声明放到run方法中,这样map就成了方法内部变量,每个线程都有一份new HashMap(),无论多少个线程执行run方法,都不会有线程安全问题。这个方法也正如应用场景中提到的,如果有多处地方使用到map,传值是个烦人的地方。

  2. 将HashMap换成Hashtable。用线程同步来解决问题,然而我们的程序只是想向一个map中写入20个整型的KEY-VALUE而已,并不需要线程同步,同步势必影响性能,得不偿失。

  3. ThreadLocal提供另外一种解决方案,即在解决方案a上边,将new  HashMap()得到的实例变量,绑定到当前线程中。之后从任何地方,都可以通过ThreadLocal获取到该变量。将程序中的注释代码恢复,再将  private final static Map map = new HashMap();注释掉,运行程序,结果就是我们想要的。

实现原理

程序调用了get()方法,我们来看一下该方法的源码

public T get() {  Thread t = Thread.currentThread();  ThreadLocalMap map = getMap(t);  if (map != null) {  ThreadLocalMap.Entry e = map.getEntry(this);  if (e != null)  return (T)e.value;  }  return setInitialValue();  }  getMap方法的源码:  ThreadLocalMap getMap(Thread t) {  return t.threadLocals;  }

该方法返回的是当前线程中的ThreadLocalMap实例。阅读Thread的源码我们发现Thread中有如下变量声明:

  ThreadLocal.ThreadLocalMap threadLocals = null;

我们暂时可以将ThreadLocalMap理解为一个类似Map的这么个类,之后再讲解它。

get()方法的大致意思就是从当前线程中拿到ThreadLocalMap的实例threadLocals,如果threadLocals不为 空,那么就以当前ThreadLocal实例为KEY从threadLocals中拿到对应的VALUE。如果不为空,那么就调用  setInitialValue()方法初始化threadLocals,最终返回的是initialValue()方法的返回值。下面是  setInitialValue()方法的源码

private T setInitialValue() {  T value = initialValue();  Thread t = Thread.currentThread();  ThreadLocalMap map = getMap(t);  if (map != null)  map.set(this, value);  else  createMap(t, value);  return value;  }

我们看到map.set(this, value);这句代码将ThreadLocalMap的实例作为KEY,将initialValue()的返回值作为VALUE,set到了threadLocals中。

程序在声明ThreadLocal实例的时候覆写了initialValue(),返回了VALUE,当然我们可以直接调用set(T t)方法来设置VALUE。下面是set(T t)方法的源码:

public void set(T value) {  Thread t = Thread.currentThread();  ThreadLocalMap map = getMap(t);  if (map != null)  map.set(this, value);  else  createMap(t, value);  }

我们看到它比setInitialValue()方法就少了个return语句。这两种方式都能达到初始化ThreadLocalMap实例的效果。

我们再来看一下ThreadLocal类的结构。

ThreadLocal类只有三个属性,如下:

private final int threadLocalHashCode = nextHashCode();

private static AtomicInteger nextHashCode = new AtomicInteger();

private static final int HASH_INCREMENT = 0x61c88647;

剩下的就是一些方法。最关键的地方就是ThreadLocal定义了一个静态内部类ThreadLocalMap。我们在下一章节再来分析这个类。 从ThreadLocal的类结构,我们可以看到,实际上问题的关键先生是ThreadLocalMap,ThreadLocal只是提供了管理的功能, 我们也可以说ThreadLocal只是代理了ThreadLocalMap而已。

ThreadLocalMap源码分析

既然ThreadLocalMap实现了类似map的功能,那我们首先来看看它的set方法源码:

private void set(ThreadLocal key, Object value) {  // We don&rsquo;t use a fast path as with get() because it is at  // least as common to use set() to create new entries as  // it is to replace existing ones, in which case, a fast  // path would fail more often than not.  Entry[] tab = table;  int len = tab.length;  int i = key.threadLocalHashCode & (len-1);  for (Entry e = tab[i];  e != null;  e = tab[i = nextIndex(i, len)]) {  ThreadLocal k = e.get();  if (k == key) {  e.value = value;  return;  }  if (k == null) {  replaceStaleEntry(key, value, i);  return;  }  }  tab[i] = new Entry(key, value);  int sz = ++size;  if (!cleanSomeSlots(i, sz) && sz >= threshold)  rehash();  }

这个方法的主要功能就是讲KEY-VALUE存储到ThreadLocalMap中,这里至少我们看到KEY实际上是  key.threadLocalHashCode,ThreadLocalMap同样维护着Entry数组,这个Entry我们在下一节会讲解。这里涉及 到了Hash冲突的处理,这里并不会向HashMap一样冲突了以链表的形式往后添加。如果对这个Hash冲突解决方案有兴趣,可以再进一步研究源码。

既然ThreadLocalMap也是用Entry来存储对象,那我们来看看Entry类的声明,Entry被定义在ThreadLocalMap的内部:

static class Entry extends WeakReference<ThreadLocal> {    Object value;  Entry(ThreadLocal k, Object v) {  super(k);  value = v;  }  }

这里我们看到Entry集成了WeakReference类,泛型声明了ThreadLocal,即每一个Entry对象都保留了对  ThreadLocal实例的弱引用,之所以这么干的原因是,线程在结束之后需要将ThreadLocal实例从map中remove调,以便回收内存空 间。

总结

首先,ThreadLocalMap并不是为了解决线程安全问题,而是提供了一种将实例绑定到当前线程的机制,类似于隔离的效果,实际上自己在方法 中new出来变量也能达到类似的效果。ThreadLocalMap跟线程安全基本不搭边,绑定上去的实例也不是多线程公用的,而是每个线程new一份, 这个实例肯定不是共用的,如果共用了,那就会引发线程安全问题。ThreadLocalMap***的用处就是用来把实例变量共享成全局变量,在程序的任何 方法中都可以访问到该实例变量而已。网上很多人说ThreadLocalMap是解决了线程安全问题,其实是望文生义,两者不是同类问题。

感谢各位的阅读!关于“Java中的ThreadLocal怎么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

--结束END--

本文标题: Java中的ThreadLocal怎么用

本文链接: https://www.lsjlt.com/news/287389.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java中的ThreadLocal怎么用
    这篇文章给大家分享的是有关Java中的ThreadLocal怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。引言ThreadLocal的官方API解释为:“该类提供了线程局部 (thread-local) &...
    99+
    2023-06-17
  • java中ThreadLocal怎么用
    这篇文章将为大家详细讲解有关java中ThreadLocal怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。package test;public class Threa...
    99+
    2023-06-02
  • ThreadLocal怎么在Java中使用
    今天就跟大家聊聊有关ThreadLocal怎么在Java中使用 ,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一.对ThreadLocal的理解ThreadLocal,很多地方叫做线...
    99+
    2023-05-31
    java threadlocal ava
  • Java中ThreadLocal类怎么使用
    这篇文章主要介绍“Java中ThreadLocal类怎么使用”,在日常操作中,相信很多人在Java中ThreadLocal类怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中ThreadLoca...
    99+
    2023-06-29
  • Java中ThreadLocal有什么用
    这篇文章将为大家详细讲解有关Java中ThreadLocal有什么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、ThreadLocal简介多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线...
    99+
    2023-06-15
  • java中的ThreadLocal是什么
    这篇文章将为大家详细讲解有关java中的ThreadLocal是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。简单介绍ThreadLocal一般称为线程本地变量,它是一种特殊的线程绑定机制,将变量与线...
    99+
    2023-06-19
  • java 中ThreadLocal 的正确用法
    java 中ThreadLocal 的正确用法用法一:在关联数据类中创建private static ThreadLocalThreaLocal的JDK文档中说明:ThreadLocal instances are typically pr...
    99+
    2023-05-31
    java threadlocal ava
  • Java中ThreadLocal的原理是什么及怎么使用
    这篇文章主要介绍“Java中ThreadLocal的原理是什么及怎么使用”,在日常操作中,相信很多人在Java中ThreadLocal的原理是什么及怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Jav...
    99+
    2023-07-06
  • java中ThreadLocal是什么
    ThreadLocal是JDK包提供的,称为线程本地变量,它将变量与线程绑定在一起,为每一个线程维护一个独立的变量副本,通过ThreadLocal可以将对象的可见范围限制在同一个线程内,从而避免了线程安全问题,对解决多线程程序的并发问题有一...
    99+
    2024-04-02
  • Java中的ThreadLocal详解
    目录一、ThreadLocal简介二、ThreadLocal简单使用 三、ThreadLocal的实现原理1、set方法源码2、get方法源码3、remove方法的实现四、Threa...
    99+
    2024-04-02
  • 怎么在java中使用ThreadLocal隔离线程
    这期内容当中小编将会给大家带来有关怎么在java中使用ThreadLocal隔离线程,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编...
    99+
    2023-06-14
  • 详解Java中的ThreadLocal
    目录一、ThreadLocal简介二、ThreadLocal简单使用三、ThreadLocal的实现原理1、set方法源码2、get方法源码3、remove方法的实现四、Thread...
    99+
    2024-04-02
  • Java中ThreadLocal的作用有哪些
    这篇文章主要介绍“Java中ThreadLocal的作用有哪些”,在日常操作中,相信很多人在Java中ThreadLocal的作用有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中ThreadLo...
    99+
    2023-06-16
  • Java中ThreadLocal的用法和原理是什么
    这篇文章主要介绍“Java中ThreadLocal的用法和原理是什么”,在日常操作中,相信很多人在Java中ThreadLocal的用法和原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中Th...
    99+
    2023-07-06
  • ThreadLocal怎么用
    这篇文章主要介绍了ThreadLocal怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1. ThreadLocal<T> 简介和使用示例ThreadLoca...
    99+
    2023-05-30
    threadlocal
  • ThreadLocal如何在Java中使用
    本篇文章给大家分享的是有关ThreadLocal如何在Java中使用,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1. 应用场景ThreadLocal 的常见应用场景有两种:多...
    99+
    2023-06-15
  • Java中ThreadLocal的用法和原理详解
    目录用法实现原理内存泄漏用法 隔离各个线程间的数据避免线程内每个方法都进行传参,线程内的所有方法都可以直接获取到ThreadLocal中管理的对象。 package com.exam...
    99+
    2023-05-15
    Java ThreadLocal用法 Java ThreadLocal原理 Java ThreadLocal
  • java中ThreadLocal的使用场景有哪些
    今天就跟大家聊聊有关java中ThreadLocal的使用场景有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。常用的java框架有哪些1.SpringMVC,Spring Web...
    99+
    2023-06-14
  • 彻底理解Java 中的ThreadLocal
     ThreadLocal是什么  早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。 ...
    99+
    2023-05-31
    java threadlocal ava
  • Java ThreadLocal的使用详解
    目录1. 应用场景1.1. 保障线程安全1.2. 显示传递参数2. 实现原理3. 注意事项ThreadLocal是线程私有的局部变量存储容器,可以理解成每个线程都有自己专属的存储容器...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作