ThreadLocal与synchronized多线程并发访问区别2【转】
来源:互联网 发布:编班软件bianban 编辑:程序博客网 时间:2024/05/22 11:36
ThreadLocal
由上面可以知道,使用同步是非常复杂的。并且同步会带来性能的降低。Java提供了另外的一种方式,通过ThreadLocal可以很容易的编写多线程程序。从字面上理解,很容易会把ThreadLocal误解为一个线程的本地变量。其它ThreadLocal并不是代表当前线程,ThreadLocal其实是采用哈希表的方式来为每个线程都提供一个变量的副本。从而保证各个线程间数据安全。每个线程的数据不会被另外线程访问和破坏。
我们把第一个例子用ThreadLocal来实现,但是我们需要些许改变。
Student并不是一个私有变量了,而是需要封装在一个ThreadLocal对象中去。调用ThreadLocal的set方法,ThreadLocal会为每一个线程都保持一份Student变量的副本。所以对student的读取操作都是通过ThreadLocal来进行的。
- protected Student getStudent() {
- Student student = (Student)studentLocal.get();
- if(student == null) {
- student = new Student();
- studentLocal.set(student);
- }
- return student;
- }
- protected void setStudent(Student student) {
- studentLocal.set(student);
- }
accessStudent()方法需要做一些改变。通过调用getStudent()方法来获得当前线程的Student变量,如果当前线程不存在一个Student变量,getStudent方法会创建一个新的Student变量,并设置在当前线程中。
Student student = getStudent();
student.setAge(age);
accessStudent()方法中无需要任何同步代码。
完整的代码清单如下:
TreadLocalDemo.java
- public class TreadLocalDemo implements Runnable {
- private final static ThreadLocal studentLocal = new ThreadLocal();
- public static void main(String[] agrs) {
- TreadLocalDemo td = new TreadLocalDemo();
- Thread t1 = new Thread(td,"a");
- Thread t2 = new Thread(td,"b");
- t1.start();
- t2.start();
- }
- /* (non-Javadoc)
- * @see java.lang.Runnable#run()
- */
- public void run() {
- accessStudent();
- }
- public void accessStudent() {
- String currentThreadName = Thread.currentThread().getName();
- System.out.println(currentThreadName+" is running!");
- Random random = new Random();
- int age = random.nextInt(100);
- System.out.println("thread "+currentThreadName +" set age to:"+age);
- Student student = getStudent();
- student.setAge(age);
- System.out.println("thread "+currentThreadName+" first read age is:"+student.getAge());
- try {
- Thread.sleep(5000);
- }
- catch(InterruptedException ex) {
- ex.printStackTrace();
- }
- System.out.println("thread "+currentThreadName +" second read age is:"+student.getAge());
- }
- protected Student getStudent() {
- Student student = (Student)studentLocal.get();
- if(student == null) {
- student = new Student();
- studentLocal.set(student);
- }
- return student;
- }
- protected void setStudent(Student student) {
- studentLocal.set(student);
- }
- }
运行程序后,屏幕输出:
b is running!
thread b set age to:0
thread b first read age is:0
a is running!
thread a set age to:17
thread a first read age is:17
thread b second read age is:0
thread a second read age is:17
可见,使用ThreadLocal后,我们不需要任何同步代码,却能够保证我们线程间数据的安全。
而且,ThreadLocal的使用也非常的简单。
我们仅仅需要使用它提供的两个方法
void set(Object obj) 设置当前线程的变量的副本的值。
Object get() 返回当前线程的变量副本
另外ThreadLocal还有一个protected的initialValue()方法。返回变量副本在当前线程的初始值。默认为null
ThreadLocal是怎么做到为每个线程都维护一个变量的副本的呢?
我们可以猜测到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多线程并发访问区别2【转】
- ThreadLocal与synchronized多线程并发访问区别1【转】
- Java synchronized关键字与多线程并发访问
- ThreadLocal与synchronized的区别
- 译 -- Java 并发编程(多线程)三 | Semaphore | ThreadLocal | synchronized
- ThreadLocal用法及与Synchronized的区别
- Java多线程与并发应用-(2)-线程互斥synchronized
- JAVA基础 (一) 并发 ThreadLocal与Synchronized 用哪一个好
- 多线程共享数据 synchronized和使用ThreadLocal区别
- 多线程volatile与synchronized区别
- 详解ThreadLocal与synchronized
- ThreadLocal与synchronized
- ThreadLocal与synchronized
- ThreadLocal与synchronized
- ThreadLocal与synchronized
- ThreadLocal与synchronized
- ThreadLocal与synchronized
- ThreadLocal与synchronized
- 让bat文件运行后不自动关闭
- SEDA(Staged Event-Driven Architecture)
- 影响Mysql性能的几个重要参数说明
- C++箴言:类型转换时定义非成员函数
- Can't find dependent libraries
- ThreadLocal与synchronized多线程并发访问区别2【转】
- 关于在英创em9161板上使用ADO.net连接远程数据库提示 “无法找到 PInvoke dll"dbnetlib.dll"”问题解决方法
- Http错误代码含义大全详解
- PHP序列化用到的构造:__sleep() __wakeup()
- CSS中元素的隐藏和显示(visibility, display)
- flex 日期处理工具类
- Genexus中取得Web工程路径的2种方法
- 凡有女孩能作到以上任意10条 那你娶她吧
- C语言基本类型及扩展