返回顶部
首页 > 资讯 > 精选 >使用ThreadLocal的作用有哪些
  • 545
分享到

使用ThreadLocal的作用有哪些

threadlocal 2023-05-31 08:05:37 545人浏览 泡泡鱼
摘要

本篇文章为大家展示了使用ThreadLocal的作用有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。ThreadLocal,直译为“线程本地”或“本地线程”,如果你真的这么认为,那就错了!其实,

本篇文章为大家展示了使用ThreadLocal的作用有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

ThreadLocal,直译为“线程本地”或“本地线程”,如果你真的这么认为,那就错了!其实,它就是一个容器,用于存放线程的局部变量,我认为应该叫做 ThreadLocalVariable(线程局部变量)才对,真不理解为什么当初 Sun 公司的工程师这样命名。
早在 jdk 1.2 的时代,java.lang.ThreadLocal 就诞生了,它是为了解决多线程并发问题而设计的,只不过设计得有些难用,所以至

今没有得到广泛使用。其实它还是挺有用的,不相信的话,我们一起来看看这个例子吧。

一个序列号生成器的程序,可能同时会有多个线程并发访问它,要保证每个线程得到的序列号都是自增的,而不能相互干扰。

先定义一个接口:

public interface Sequence { int getNumber();}

每次调用 getNumber() 方法可获取一个序列号,下次再调用时,序列号会自增。
再做一个线程类:

public class ClientThread extends Thread { private Sequence sequence; public ClientThread(Sequence sequence) {  this.sequence = sequence; } @Override public void run() {  for (int i = 0; i < 3; i++) {   System.out.println(Thread.currentThread().getName() + " => " + sequence.getNumber());  } }}

在线程中连续输出三次线程名与其对应的序列号。
我们先不用 ThreadLocal,来做一个实现类吧。

public class SequenceA implements Sequence { private static int number = 0; public int getNumber() {  number = number + 1;  return number; } public static void main(String[] args) {  Sequence sequence = new SequenceA();  ClientThread thread1 = new ClientThread(sequence);  ClientThread thread2 = new ClientThread(sequence);  ClientThread thread3 = new ClientThread(sequence);  thread1.start();  thread2.start();  thread3.start(); }}

序列号初始值是0,在 main() 方法中模拟了三个线程,运行后结果如下:
Thread-0 => 1
Thread-0 => 2
Thread-0 => 3
Thread-2 => 4
Thread-2 => 5
Thread-2 => 6
Thread-1 => 7
Thread-1 => 8
Thread-1 => 9

由于线程启动顺序是随机的,所以并不是0、1、2这样的顺序,这个好理解。为什么当 Thread-0 输出了1、2、3之后,而 Thread-2 却输出了4、5、6呢?线程之间竟然共享了 static 变量!这就是所谓的“非线程安全”问题了。

那么如何来保证“线程安全”呢?对应于这个案例,就是说不同的线程可拥有自己的 static 变量,如何实现呢?下面看看另外一个实现吧。

public class SequenceB implements Sequence { private static ThreadLocal<Integer> numberContainer = new ThreadLocal<Integer>() {  @Override  protected Integer initialValue() {   return 0;  } }; public int getNumber() {  numberContainer.set(numberContainer.get() + 1);  return numberContainer.get(); } public static void main(String[] args) {  Sequence sequence = new SequenceB();  ClientThread thread1 = new ClientThread(sequence);  ClientThread thread2 = new ClientThread(sequence);  ClientThread thread3 = new ClientThread(sequence);  thread1.start();  thread2.start();  thread3.start(); }}

通过 ThreadLocal 封装了一个 Integer 类型的 numberContainer 静态成员变量,并且初始值是0。再看 getNumber() 方法,首先从 numberContainer 中 get 出当前的值,加1,随后 set 到 numberContainer 中,最后将 numberContainer 中 get 出当前的值并返回。

是不是很恶心?但是很强大!确实稍微饶了一下,我们不妨把 ThreadLocal 看成是一个容器,这样理解就简单了。所以,这里故意用 Container 这个单词作为后缀来命名 ThreadLocal 变量。

运行结果如何呢?看看吧。

Thread-0 => 1
Thread-0 => 2
Thread-0 => 3
Thread-2 => 1
Thread-2 => 2
Thread-2 => 3
Thread-1 => 1
Thread-1 => 2
Thread-1 => 3

每个线程相互独立了,同样是 static 变量,对于不同的线程而言,它没有被共享,而是每个线程各一份,这样也就保证了线程安全。 也就是说,TheadLocal 为每一个线程提供了一个独立的副本!

搞清楚 ThreadLocal 的原理之后,有必要总结一下 ThreadLocal 的 api,其实很简单。
1.public void set(T value):将值放入线程局部变量中
2.public T get():从线程局部变量中获取值
3.public void remove():从线程局部变量中移除值(有助于 JVM 垃圾回收)
4.protected T initialValue():返回线程局部变量中的初始值(默认为 null) 

为什么 initialValue() 方法是 protected 的呢?就是为了提醒程序员们,这个方法是要你们来实现的,请给这个线程局部变量一个初始值吧。

了解了原理与这些 API,其实想想 ThreadLocal 里面不就是封装了一个 Map 吗?自己都可以写一个 ThreadLocal 了,尝试一下吧。

public class MyThreadLocal<T> { private Map<Thread, T> container = Collections.synchronizedMap(new HashMap<Thread, T>()); public void set(T value) {  container.put(Thread.currentThread(), value); } public T get() {  Thread thread = Thread.currentThread();  T value = container.get(thread);  if (value == null && !container.containsKey(thread)) {   value = initialValue();   container.put(thread, value);  }  return value; } public void remove() {  container.remove(Thread.currentThread()); } protected T initialValue() {  return null; }}

以上完全山寨了一个 ThreadLocal,其中中定义了一个同步 Map(为什么要这样?请读者自行思考),代码应该非常容易读懂。
下面用这 MyThreadLocal 再来实现一把看看。

public class SequenceC implements Sequence { private static MyThreadLocal<Integer> numberContainer = new MyThreadLocal<Integer>() {  @Override  protected Integer initialValue() {   return 0;  } }; public int getNumber() {  numberContainer.set(numberContainer.get() + 1);  return numberContainer.get(); } public static void main(String[] args) {  Sequence sequence = new SequenceC();  ClientThread thread1 = new ClientThread(sequence);  ClientThread thread2 = new ClientThread(sequence);  ClientThread thread3 = new ClientThread(sequence);  thread1.start();  thread2.start();  thread3.start(); }}

以上代码其实就是将 ThreadLocal 替换成了 MyThreadLocal,仅此而已,运行效果和之前的一样,也是正确的。
其实 ThreadLocal 可以单独成为一种设计模式,就看你怎么看了。 

ThreadLocal 具体有哪些使用案例呢?通过 ThreadLocal 存放 JDBC Connection,以达到事务控制的能力。

上述内容就是使用ThreadLocal的作用有哪些,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网精选频道。

--结束END--

本文标题: 使用ThreadLocal的作用有哪些

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

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

猜你喜欢
  • 使用ThreadLocal的作用有哪些
    本篇文章为大家展示了使用ThreadLocal的作用有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。ThreadLocal,直译为“线程本地”或“本地线程”,如果你真的这么认为,那就错了!其实,...
    99+
    2023-05-31
    threadlocal
  • Java中ThreadLocal的作用有哪些
    这篇文章主要介绍“Java中ThreadLocal的作用有哪些”,在日常操作中,相信很多人在Java中ThreadLocal的作用有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中ThreadLo...
    99+
    2023-06-16
  • java中ThreadLocal的使用场景有哪些
    今天就跟大家聊聊有关java中ThreadLocal的使用场景有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。常用的java框架有哪些1.SpringMVC,Spring Web...
    99+
    2023-06-14
  • Java之ThreadLocal使用常见和方式有哪些
    这篇文章主要介绍了Java之ThreadLocal使用常见和方式有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1 两大使用场景-ThreadLocal的用途典型场景1:...
    99+
    2023-06-20
  • ThreadLocal的问题有哪些
    这篇文章主要介绍“ThreadLocal的问题有哪些”,在日常操作中,相信很多人在ThreadLocal的问题有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Thread...
    99+
    2024-04-02
  • 有哪些使用Vue.set的副作用
    本篇内容主要讲解“有哪些使用Vue.set的副作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“有哪些使用Vue.set的副作用”吧!Vue虽然用挺久了,还是会...
    99+
    2024-04-02
  • 使用HttpServletRequest对象的作用有哪些
    这篇文章将为大家详细讲解有关使用HttpServletRequest对象的作用有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。  使用HttpServletRequest可以防止盗链行为...
    99+
    2023-05-31
    httpservletrequest ue
  • javascript的作用有哪些
    本篇文章为大家展示了javascript的作用有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 javascript主要用于:1、使...
    99+
    2024-04-02
  • RPC的作用有哪些
    本篇内容主要讲解“RPC的作用有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“RPC的作用有哪些”吧!OSI 网络七层模型在说 RPC 和 HTTP 的区别...
    99+
    2024-04-02
  • @DateTimeFormat的作用有哪些
    本篇内容主要讲解“@DateTimeFormat的作用有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“@DateTimeFormat的作用有哪些”吧!本文提...
    99+
    2024-04-02
  • css3的作用有哪些
    本篇文章为大家展示了css3的作用有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。CSS3是CSS2的升级版本,3只是版本号,它在CSS2.1 的基础上增加了很多强大的新功能,目前主浏览器 Ch...
    99+
    2023-06-15
  • Vuex的作用有哪些
    这篇文章给大家分享的是有关Vuex的作用有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。概述想必用过 vue.js 的童鞋,一定知道在 vue 各个组件之间传值的痛苦,基于父子、兄弟组件,我们传值可能会很方便...
    99+
    2023-06-15
  • phpinclude的作用有哪些
    1. 代码重用:phpinclude可以将一个PHP文件中的代码引入到另一个PHP文件中,实现代码的重用。2. 维护性:将具有相同功...
    99+
    2023-06-13
    phpinclude
  • Python的作用有哪些
    本篇内容主要讲解“Python的作用有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python的作用有哪些”吧!Python能干什么1、web开发领域2、机器学习领域3、游戏开发领域4、科...
    99+
    2023-06-15
  • jQuery的作用有哪些
    今天小编给大家分享一下jQuery的作用有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。jQuery是什么?jQuery...
    99+
    2023-06-27
  • Jqgrid的作用有哪些
    JqGrid是一个基于jQuery的表格插件,用于在网页上展示和操作数据。它具有以下作用:1. 数据展示:JqGrid可以将数据以表...
    99+
    2023-09-11
    Jqgrid
  • powershell的作用有哪些
    今天小编给大家分享一下powershell的作用有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。powershell能干...
    99+
    2023-07-05
  • php的作用有哪些
    这篇文章主要讲解了“php的作用有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php的作用有哪些”吧!php即“超文本预处理器”,是在服务器端执行的脚本语言,用于web开发;php的作...
    99+
    2023-07-05
  • Kotlin的作用有哪些
    Kotlin的作用有以下几个: Android开发:Kotlin可以用于开发Android应用程序,它与Java语言兼容,可以与...
    99+
    2023-10-25
    Kotlin
  • css的作用有哪些
    这篇文章给大家分享的是有关css的作用有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。css的作用是:1、主要用来设计网页的样式,美化网页;2、能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体...
    99+
    2023-06-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作