ThreadLocal与Synchronized的用法

来源:http://blog.csdn.net/wl_ldy/article/details/5948779

一.ThreadLocal的用法

ThreadLocal的实现:

package com.sodao.lucene;     import java.util.Random;     public class ThreadLocalTest implements Runnable{     ThreadLocal<Studen> studenThreadLocal = new ThreadLocal<Studen>();     @Override    public void run() {     String currentThreadName = Thread.currentThread().getName();     System.out.println(currentThreadName + " is running...");     Random random = new Random();     int age = random.nextInt(100);     System.out.println(currentThreadName + " is set age: "  + age);     Studen studen = getStudent(); //通过这个方法,为每个线程都独立的new一个student对象,每个线程的的student对象都可以设置不同的值     studen.setAge(age);     System.out.println(currentThreadName + " is first get age: " + studen.getAge());     try {     Thread.sleep(500);     } catch (InterruptedException e) {     e.printStackTrace();     }     System.out.println( currentThreadName + " is second get age: " + studen.getAge());     }     private Studen getStudent() {     Studen studen = studenThreadLocal.get();     if (null == studen) {     studen = new Studen();     studenThreadLocal.set(studen);     }     return studen;     }     public static void main(String[] args) {     ThreadLocalTest t = new ThreadLocalTest();     Thread t1 = new Thread(t,"Thread A");     Thread t2 = new Thread(t,"Thread B");     t1.start();     t2.start();     }     }     class Studen{     int age;     public int getAge() {     return age;     }     public void setAge(int age) {     this.age = age;     }     }    

Synchronized的实现:

package com.sodao.lucene;     import java.util.Random;     public class MultiThreadTest  implements Runnable{     Studen studen = new Studen();     @Override    public void run() {     String currentThreadName = Thread.currentThread().getName();     System.out.println(currentThreadName + " is running ....");     //同步     synchronized (studen) {     Random random = new Random();     int age = random.nextInt(100);     studen.setAge(age);     System.out.println(currentThreadName + " is set age: " + age);     System.out.println(currentThreadName + "is first get age: " + studen.getAge() );     try {     Thread.sleep(500);     } catch (InterruptedException e) {     e.printStackTrace();     }     System.out.println(currentThreadName + " is second get age: " + studen.getAge() );     }     }     public static void main(String[] args) {     MultiThreadTest m = new MultiThreadTest();     Thread t1 = new Thread(m,"Thread A");     Thread t2 = new Thread(m,"Thread B");     t1.start();     t2.start();     }     
}     class Student {     int age;     public int getAge() {     return age;     }     public void setAge(int age) {     this.age = age;     }     }    
以上2中方法都实现的功能相同,但方法不一样 

ThreadLocal使用场合主要解决多线程中数据数据因并发产生不一致问题。 ThreadLocal为每个线程的中并发访问的数据提供一个副本 ,通过访问副本来运行业务,这样的结果是耗费了内存,单大大减少了线程同步所带来性能消耗,也减少了线程并发控制的复杂度。 

ThreadLocal不能使用原子类型,只能使用Object类型。ThreadLocal的使用比synchronized要简单得多。 

ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。 synchronized是利用锁的机制,使变量或代码块在某一时刻只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。 而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。 

Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。  

当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。 

ThreadLocal使用的一般步骤: 

1、在多线程的类(如ThreadDemo类)中,创建一个ThreadLocal对象threadXxx,用来保存线程间需要隔离处理的对象xxx。 
2、在ThreadDemo类中,创建一个获取要隔离访问的数据的方法getXxx(),在方法中判断,若ThreadLocal对象为null时候,应该new()一个隔离访问类型的对象,并强制转换为要应用的类型。 
3、在ThreadDemo类的run()方法中,通过getXxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。


二.ThreadLocal的实现原理:
public class ThreadLocal     
{     private Map values = Collections.synchronizedMap(new HashMap());     public Object get()     {     Thread curThread = Thread.currentThread();      Object o = values.get(curThread);      if (o == null && !values.containsKey(curThread))     {     o = initialValue();     values.put(curThread, o);      }     return o;      }     public void set(Object newValue)     {     values.put(Thread.currentThread(), newValue);     }     public Object initialValue()     {     return null;      }     
}    
由此可见,ThreadLocal通过一个Map来为每个线程都持有一个变量副本。这个map以当前线程为key。与synchronized相比,ThreadLocal是以空间换时间的策略来实现多线程程序。 

Synchronized还是ThreadLocal? 
ThreadLocal以空间换取时间,提供了一种非常简便的多线程实现方式。因为多个线程并发访问无需进行等待,所以使用ThreadLocal会获得更大的性能。虽然使用ThreadLocal会带来更多的内存开销,但这点开销是微不足道的。因为保存在ThreadLocal中的对象,通常都是比较小的对象。另外使用ThreadLocal不能使用原子类型,只能使用Object类型。ThreadLocal的使用比synchronized要简单得多。 
ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。 
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。 
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。



2012-05-23新增
每一个线程都维护一个本地对象的副本,类图如:



ThreadLocal 只是提供当前线程(Thread.currentThread( ) )对副本(ThreadLocal.ThreadLocalMap)的操作。
部分源代码
    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();}
    ThreadLocalMap getMap(Thread t) {return t.threadLocals;}


疑问:ThreadLocal每种类型的对象只能存储一个?
应该是的,因为 map 的key 值是 ThreadLocal对象。下面是 ThreadLocal 部分源代码:
    public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/497934.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java程序员面试需要注意什么_Java程序员面试时要注意的一些问题

Java程序员面试的时候会面临各种五花八门的问题&#xff0c;你的第一反应、思维逻辑、思考方法&#xff0c;专业水平决定了企业对你的评价和你的薪资水准&#xff0c;但是除了专业以外还有一些你需要避免出现错误的注意事项&#xff0c;如果很好的避免了&#xff0c;就能帮你在…

“强化学习之父”萨顿:预测学习马上要火,AI将帮我们理解人类意识

李杉 编译自 KDnuggets量子位 出品 | 公众号 QbitAI地处加拿大埃德蒙顿的阿尔伯塔大学&#xff08;UAlberta&#xff09;可谓是强化学习重镇&#xff0c;这项技术的缔造者之一萨顿&#xff08;Rich Sutton&#xff09;在这里任教。△ 萨顿萨顿常被称为“强化学习之父”&#xf…

cmd中java编译命令是什么_cmd中java的编译命令——java和javac、javap

如题&#xff0c;首先我们在桌面&#xff0c;开始->运行->键入cmd 回车&#xff0c;进入windows命令行。进入如图所示的画面&#xff1a;可知&#xff0c;当前默认目录为C盘Users文件夹下的Administrator文件夹。一般而言&#xff0c;我们习惯改变当前目录。由于windows有…

Struts2源码阅读(一)_Struts2框架流程概述

1. Struts2架构图 请求首先通过Filter chain&#xff0c;Filter主要包括ActionContextCleanUp&#xff0c;它主要清理当前线程的ActionContext和Dispatcher&#xff1b;FilterDispatcher主要通过AcionMapper来决定需要调用哪个Action。 ActionMapper取得了ActionMappi…

如何衡量机器与人类的智能关系,AI智商评测标准专家研讨会邀请

21世纪以来&#xff0c;人工智能领域陆续爆发很多重要事件。其中最吸引人们眼球的&#xff0c;当属2016年战胜了人类围棋冠军并开始能够从0自我学习的AlphaGo。10月26日&#xff0c;软银CEO孙正义在沙特阿拉伯举行的未来投资计划大会上称&#xff0c;未来30年内AI的智商&#x…

谷歌Jeff Dean团队发文,探讨「学习模型」如何替代传统索引结构

原文来源&#xff1a;arxiv-vanity作者&#xff1a;Tim Kraska、Alex Beutel、Ed H. Chi、Jeffrey Dean、Neoklis Polyzotis「雷克世界」编译&#xff1a;嗯~阿童木呀、多啦A亮、我是卡布达索引就是模型&#xff1a;B-Tree-Index可以看作是一个能够将一个键映射到排序数组中记录…

php html区别_php与html区别

php与html区别HTML是超文本标记语言&#xff1b;PHP即“超文本预处理器”&#xff0c;是一种通用开源脚本语言。PHP 独特的语法混合了 C、Java、Perl 以及 PHP 自创新的语法。HTML主要用在客户端的显示&#xff0c;比如我们浏览的网页&#xff0c;特别是静态网页&#xff0c;都…

Struts2源码阅读(三)_DispatcherConfigurationProvider

首先强调一下struts2的线程程安全&#xff0c;在Struts2中大量采用ThreadLocal线程局部变量的方法来保证线程的安全,像Dispatcher等都是通过ThreadLocal来保存变量值,使得每个线程都有自己独立的实例变量,互不相干. 接下来就从Dispatcher开始看起&#xff0c;先看其构造函数&a…

谷歌宣布在北京成立AI中国中心:李飞飞和李佳共同领导

来源&#xff1a;澎湃新闻概要&#xff1a;谷歌正式宣布谷歌AI中国中心&#xff08;Google AI China Center&#xff09;在北京成立。谷歌正式宣布谷歌AI中国中心&#xff08;Google AI China Center&#xff09;在北京成立。12月13日&#xff0c;在上海举行的谷歌开发者大会&a…

AI 与区块链:两大热门技术,会碰撞出什么样的火花?

来源&#xff1a;36氪概要&#xff1a;区块链和AI可以说是当今最热门的两个技术方向了。区块链和AI可以说是当今最热门的两个技术方向了。在一般人看来&#xff0c;这两大技术似乎没有什么交叉的地方&#xff0c;因为区块链和AI分别属于是技术谱系的两个极端&#xff1a;一个是…

伯克利人工智能研究院最新研究:协作型工业机器人如何更智能?

原文来源&#xff1a;BAIR作者&#xff1a;Changliu Liu、Masayoshi Tomizuka「雷克世界」编译&#xff1a;嗯~阿童木呀、我是卡布达在现代工厂中&#xff0c;工人和机器人是两大主要劳动力。出于安全考虑&#xff0c;这两者通常被限制在金属笼中的机器人分离开来&#xff0c;而…

Php如何过360拦截,PHP常见漏洞修复文件-360漏洞修复插件

主要对常见的漏洞进行拦截&#xff0c;如&#xff1a;SQL注入漏洞、检测POST数据、XSS漏洞防护等&#xff0c;效果非常不错&#xff0c;值得拥有。1、下载:360漏洞修复插件2、解压后&#xff0c;上传整个文件夹至服务器根目录3、if(is_file($_SERVER[DOCUMENT_ROOT]./360safe/3…

谷歌开源 TFGAN,让训练和评估 GAN 变得更加简单

作者&#xff1a;思颖概要&#xff1a;训练神经网络的时候&#xff0c;通常需要定义一个损失函数来告诉网络它离目标还有多远。三年前&#xff0c;蒙特利尔大学 Ian Goodfellow 等学者提出「生成式对抗网络」&#xff08;Generative Adversarial Networks&#xff0c;GANs&…

Struts2源码阅读(六)_ActionProxyActionInvocation

下面开始讲一下主菜ActionProxy了.在这之前最好先去了解一下动态Proxy的基本知识.ActionProxy是Action的一个代理类&#xff0c;也就是说Action的调用是通过ActionProxy实现的&#xff0c;其实就是调用了ActionProxy.execute()方法&#xff0c;而该方法又调用了ActionInvocatio…

py语言和php,php和python什么区别

python语言的风格Python在设计上坚持了清晰划一的风格&#xff0c;这使得Python成为一门易读、易维护&#xff0c;并且被大量用户所欢迎的、用途广泛的语言。设计者开发时总的指导思想是&#xff0c;对于一个特定的问题&#xff0c;只要有一种最好的方法来解决就好了。这在由Ti…

计算机产业深度报告:云计算与人工智能开启新一轮技术变革周期

来源&#xff1a;乐晴智库概要&#xff1a;每一次的技术迭代都将行业推向新的高度&#xff0c;同时也对产业生态和企业兴衰产生重大影响。纵观整个IT产业的发展史&#xff0c;从1960年代到现在的2010年代&#xff0c;科技行业历经了大型机时代、小型机时代、PC时代、互联网时代…

自动分页,返回时跳回指定页

实现原理&#xff1a; displaytag 自动分页时&#xff0c;只需要提供一个“集合”(name 属性) 和翻页对应的 requestURI 属性&#xff08;也是返回整体的集合&#xff09; 执行翻页时 displaytag 会自动计算出页数&#xff0c;形如&#xff1a; http://localhost:8080/bpp/ma…

java 界面艺术字,Java 在Word文档中添加艺术字

与普通文字相比&#xff0c;艺术字更加美观有趣也更具有辨识度&#xff0c;常见于一些设计精美的杂志或宣传海报中。我们在日常工作中编辑Word文档时&#xff0c;也可以通过添加艺术字体来凸显文章的重点,美化页面排版。这篇文章将介绍如何使用FreeSpire.Doc for Java在word文档…

AI校招程序员最高薪酬曝光!腾讯80万年薪领跑,还送北京户口

来源&#xff1a;100offer概要&#xff1a;如果说 2016 年是互联网 AI 领域井喷的元年&#xff0c;2017 年整个 AI 领域全面爆发&#xff0c;来潮汹涌的趋势相较 2016 年可以说是有过之而无不及。如果说 2016 年是互联网 AI 领域井喷的元年&#xff0c;2017 年整个 AI 领域全面…

vscode php断点,VSCode中设置断点调试PHP(示例代码)

所需文件xampp 集成服务器(本文使用Apache2.4MySQLPHP7.4.3)vscodeXdebugphp-debug 插件配置Xdebug1. 下载Xdebug插件 (直接去 https://xdebug.org/download.php下载php对应版本的插件)如果不知道如何选取版本&#xff0c;则如下Step 1&#xff1a;获取本地php版本信息 (利用ph…