ThreadLocal 详解
什么是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 详解的更多相关文章
- android Handler机制之ThreadLocal详解
		
概述 我们在谈Handler机制的时候,其实也就是谈Handler.Message.Looper.MessageQueue之间的关系,对于其工作原理我们不做详解(Handler机制详解). Messa ...
 - 深入解析ThreadLocal 详解、实现原理、使用场景方法以及内存泄漏防范 多线程中篇(十七)
		
简介 从名称看,ThreadLocal 也就是thread和local的组合,也就是一个thread有一个local的变量副本 ThreadLocal提供了线程的本地副本,也就是说每个线程将会拥有一个 ...
 - ThreadLocal详解(实现多线程同步访问变量)
		
ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...
 - java核心知识点学习----多线程间的数据共享和对象独立,ThreadLocal详解
		
线程内的数据共享与对象独立,举例:张三给李四转钱,开启A线程去执行转钱这个动作,刚好同时王五给赵六转钱,开启B线程去执行转钱,因为是调用的同样一个动作或者说对象,所以如果不能保证线程间的对象独立,那么 ...
 - ThreadLocal详解
		
ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...
 - 【Java并发系列03】ThreadLocal详解
		
img { border: solid 1px } 一.前言 ThreadLocal这个对象就是为多线程而生的,没有了多线程ThreadLocal就没有存在的必要了.可以将任何你想在每个线程独享的对象 ...
 - 并发系列(2)之 ThreadLocal  详解
		
本文将主要结合源码讲述 ThreadLocal 的使用场景和内部结构,以及 ThreadLocalMap 的内部结构:另外在阅读文本之前只好先了解一下引用和 HashMap 的相关知识,可以参考 Re ...
 - ThreadLocal详解,ThreadLocal源码分析,ThreadLocal图解
		
本文脉路: 概念阐释 ----> 原理图解 ------> 源码分析 ------> 思路整理 ----> 其他补充. 一.概念阐述. ThreadLocal 是一个为 ...
 - 【Java深入研究】7、ThreadLocal详解
		
ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...
 - ThreadLocal详解,处理成员变量线程不安全的情况
		
ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...
 
随机推荐
- pgadmin导出excel
			
生成导入sql 第一行公式:="insert into province(code,name) values("&A2&",'"&B2& ...
 - 【整理】Git相关资料
			
http://book.51cto.com/art/201107/278731.htm http://book.51cto.com/art/201107/278828.htm
 - [整理]x=x++和x=++x
			
最近看java面试题,再次遇到x=x++,之前一直按照C语言中对自增运算符++的解释去理解.殊不知自己犯了严重的错误. (1)不同的语言的编译器,会导致相同的代码最终执行的结果不确定; (2)而且就算 ...
 - JavaScript绝句的小研究
			
前几日在网上看到一篇文章:JavaScript绝句,看了以后觉得里面的代码颇为有趣,不过文章里面只是简单的说了这样写的目的和结果,却没有令读者起到既知其然,又知其所以然的效果.这里简单写一篇小文章剖析 ...
 - 字符串对象的charAt函数存在的意义
			
var style = ""; style[0] //undefined var style = ""; style.charAt(0); //"&q ...
 - Java并发——线程同步Volatile与Synchronized详解
			
0. 前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52370068 面试时很可能遇到这样一个问题:使用volatile修饰in ...
 - C语言清空输入缓冲区的N种方法对比【转】
			
转自:http://www.cnblogs.com/codingmylife/archive/2010/04/18/1714954.html C语言中有几个基本输入函数: //获取字符系列 int f ...
 - Linux下USB suspend/resume源码分析【转】
			
转自:http://blog.csdn.net/aaronychen/article/details/3928479 Linux下USB suspend/resume源码分析 Author:aaron ...
 - three.js 初探
			
2014年3月3日 22:18:40 简单旋转立方体: http://blog.163.com/hailin_xin/blog/static/21816219020136103402812 简单球体入 ...
 - 最完整的PS快捷键大全(绝对经典)
			
快速恢复默认值 有些不擅长Photoshop的朋友为了调整出满意的效果真是几经周折,结果发现还是原来的默认效果最好,这下傻了眼,后悔不该当初呀!怎么恢复到默认值呀?试着轻轻点按选项栏上的工具图标,然后 ...