什么是ThreadLocal

根据JDK文档中的解释:ThreadLocal的作用是提供线程内的局部变量,这种变量在多线程环境下访问时能够保证各个线程里变量的独立性。

从这里可以看出,引入ThreadLocal的初衷是为了提供线程内的局部变量

ThreadLocal 不是一个线程,而是一个线程的本地化对象。当某个变量在使用 ThreadLocal 进行维护时,ThreadLocal 为使用该变量的每个线程分配了一个独立的变量副本。

每个线程可以自行操作自己对应的变量副本,而不会影响其他线程的变量副本。

API 方法

ThreadLocal 的 API 提供了如下的 4 个方法。

1)protected T initialValue()

返回当前线程的局部变量副本的变量初始值。


2)T get()

返回当前线程的局部变量副本的变量值,如果此变量副本不存在,则通过 initialValue() 方法创建此副本并返回初始值。


3)void set(T value)

设置当前线程的局部变量副本的变量值为指定值。


4)void remove()

删除当前线程的局部变量副本的变量值。


在实际使用中,我们一般都要重写 initialValue() 方法,设置一个特定的初始值。

关于initialValue的初始化。本人尝试了多种方式:

 //new ThreadLocal方式:不推荐
final ThreadLocal<String> commandThreads = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return "execute :"+System.currentTimeMillis();
}
};
System.out.println(commandThreads.get());

  

 //withInitial方式:
ThreadLocal<String> commandThreadnew =
// ThreadLocal.withInitial(()-> "execute :"+System.currentTimeMillis());
ThreadLocal.withInitial(()->new String("execute :"+System.currentTimeMillis()));
System.out.println(commandThreadnew.get());

  

 //(new Supplier<String>(){}方式 推荐
ThreadLocal<String> commandThreadnew1 =
ThreadLocal.withInitial(new Supplier<String>() {
@Override
public String get() {
return "execute :"+System.currentTimeMillis();
}
}); System.out.println( commandThreadnew1.get());

  

以下是关于ThreadLocal 解决多线程变量共享问题:

存在争议点:

ThreadLocal到底能不能解决共享对象的多线程访问问题?

package com.wuxianjiezh.demo.threadpool;

public class MainTest {

    public static void main(String[] args) {
Bank bank = new Bank();
Thread xMThread = new Thread(() -> bank.deposit(200), "小明");
Thread xGThread = new Thread(() -> bank.deposit(200), "小刚");
Thread xHThread = new Thread(() -> bank.deposit(200), "小红");
xMThread.start();
xGThread.start();
xHThread.start();
}
} class Bank { private int money = 1000; public void deposit(int money) {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + "--当前账户余额为:" + this.money);
this.money += money;
System.out.println(threadName + "--存入 " + money + " 后账户余额为:" + this.money);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

  运行结果:存在多线程输出结果混乱

小明--当前账户余额为:1000
小红--当前账户余额为:1000
小红--存入 200 后账户余额为:1400
小刚--当前账户余额为:1000
小刚--存入 200 后账户余额为:1600
小明--存入 200 后账户余额为:1200

  

使用 ThreadLocal 保存对象的局部变量。

public class MainTest {

    public static void main(String[] args) {
Bank bank = new Bank();
Thread xMThread = new Thread(() -> bank.deposit(200), "小明");
Thread xGThread = new Thread(() -> bank.deposit(200), "小刚");
Thread xHThread = new Thread(() -> bank.deposit(200), "小红");
xMThread.start();
xGThread.start();
xHThread.start();
}
} class Bank { // 初始化账户余额为 100
ThreadLocal<Integer> account = ThreadLocal.withInitial(new Supplier<Integer>() {
@Override
public Integer get() {
return 1000;
}
}); public void deposit(int money) {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + "--当前账户余额为:" + account.get());
account.set(account.get() + money);
System.out.println(threadName + "--存入 " + money + " 后账户余额为:" + account.get());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

  运行结果为:

小明--当前账户余额为:1000
小红--当前账户余额为:1000
小红--存入 200 后账户余额为:1200
小刚--当前账户余额为:1000
小刚--存入 200 后账户余额为:1200
小明--存入 200 后账户余额为:1200
可以看到,我们要的效果达到了。各线程间同时操作自己的变量,相互间没有影响。

  

ThreadLocal 与 Thread 同步机制的比较

  • 同步机制采用了以时间换空间方式,通过对象锁保证在同一个时间,对于同一个实例对象,只有一个线程访问。

  • ThreadLocal 采用以空间换时间方式,为每一个线程都提供一份变量,各线程间同时访问互不影响。

转载请注明出处:https://segmentfault.com/a/1190000009236777

ThreadLocal 详解的更多相关文章

  1. android Handler机制之ThreadLocal详解

    概述 我们在谈Handler机制的时候,其实也就是谈Handler.Message.Looper.MessageQueue之间的关系,对于其工作原理我们不做详解(Handler机制详解). Messa ...

  2. 深入解析ThreadLocal 详解、实现原理、使用场景方法以及内存泄漏防范 多线程中篇(十七)

    简介 从名称看,ThreadLocal 也就是thread和local的组合,也就是一个thread有一个local的变量副本 ThreadLocal提供了线程的本地副本,也就是说每个线程将会拥有一个 ...

  3. ThreadLocal详解(实现多线程同步访问变量)

    ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...

  4. java核心知识点学习----多线程间的数据共享和对象独立,ThreadLocal详解

    线程内的数据共享与对象独立,举例:张三给李四转钱,开启A线程去执行转钱这个动作,刚好同时王五给赵六转钱,开启B线程去执行转钱,因为是调用的同样一个动作或者说对象,所以如果不能保证线程间的对象独立,那么 ...

  5. ThreadLocal详解

    ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...

  6. 【Java并发系列03】ThreadLocal详解

    img { border: solid 1px } 一.前言 ThreadLocal这个对象就是为多线程而生的,没有了多线程ThreadLocal就没有存在的必要了.可以将任何你想在每个线程独享的对象 ...

  7. 并发系列(2)之 ThreadLocal 详解

    本文将主要结合源码讲述 ThreadLocal 的使用场景和内部结构,以及 ThreadLocalMap 的内部结构:另外在阅读文本之前只好先了解一下引用和 HashMap 的相关知识,可以参考 Re ...

  8. ThreadLocal详解,ThreadLocal源码分析,ThreadLocal图解

    本文脉路: 概念阐释 ---->  原理图解  ------> 源码分析 ------>  思路整理  ----> 其他补充. 一.概念阐述. ThreadLocal 是一个为 ...

  9. 【Java深入研究】7、ThreadLocal详解

    ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...

  10. ThreadLocal详解,处理成员变量线程不安全的情况

    ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...

随机推荐

  1. spring Mvc Web 编码相关 [model 到 视图传递数据] (九)

    在某种编码环境,由bean注解的参数可能会发生乱码问题. 即可页面web.xml或其他地方都设备UTF-8, 但还是会有这样的问题. 首先不要使用model传到视图的数据. 第二,不要request. ...

  2. HDU 2086 A=? 数学题

    题目描述:有一个公式,Ai = (Ai-1 + Ai+1)/2 - Ci (i = 1, 2, 3, .... n).,如果给出A0, An+1, 和 C1, C2, .....Cn要你计算出A1是多 ...

  3. GBDT理解

    一.提升树 提升方法实际采用加法模型(即基函数的线性组合)与前向分布算法.以决策树为基函数的提升方法称为提升树,boosting tree.对分类问题的决策树是二叉分类树,对回归问题的决策树是二叉回归 ...

  4. lucene入门查询索引——(三)

    1.用户接口(lucene不提供)

  5. 【干货】SIFT-Workstation 下载与安装 不跳过每一个细节部分

    SIFT-Workstation.ova     下载地址https://digital-forensics.sans.org/community/download-sift-kit       ov ...

  6. 初始ASP.NET数据控件【续 DataList】

    DataList控件  DataList控件也是一个常用的数据绑定控件,相对于GridView控件虽然没它那么强大的功能,但是灵活性却很强势.因为其本身就是一个富有弹性的控件.DataList控件可以 ...

  7. ecplise里的run as里只有run configurations是怎么回事?

    一.没有main方法 二.main方法所在的类不是在与文件名同名的类中

  8. [转] caffe视觉层Vision Layers 及参数

    视觉层包括Convolution, Pooling, Local Response Normalization (LRN), im2col等层. 1.Convolution层: 就是卷积层,是卷积神经 ...

  9. **15.app后端怎么设计用户登录方案(API权限安全)

    在很多app中,都需要用户的登录操作.登录,就需要用到用户名和密码.为了安全起见,暴露明文密码的次数越少越好.怎么能最大程度避免泄露用户的密码呢?在登录后,app后端怎么去验证和维持用户的登录状态呢? ...

  10. Java编程的逻辑 (67) - 线程的基本协作机制 (上)

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...