(三) Java多线程详解之线程范围内共享变量及ThreadLocal类使用
2017-05-20 11:03
721 查看
线程范围内共享变量
HashTable方式实现
在开发中经常会遇到一种情况:有一个变量会被多个线程访问,但是要确保同个线程内访问的是同一个对象,Hashtable方式实现代码如下:public class ThreadExample5 { private static Map<Thread, Integer> threadData = new Hashtable<Thread, Integer>(); public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { int data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " has put data :" + data); threadData.put(Thread.currentThread(), data); new A().get(); new B().get(); } }).start(); } } static class A { public void get() { System.out.println(threadData); int data = threadData.get(Thread.currentThread()); System.out.println("A from " + Thread.currentThread().getName() + " get data :" + data); } } static class B { public void get() { int data = threadData.get(Thread.currentThread()); System.out.println("B from " + Thread.currentThread().getName() + " get data :" + data); } } }
注意这里用到的是Hashtable(线程安全)来区分每个线程,网上很多资料写的都是用HashMap(线程不安全),我经过实际测试发现此处用HashMap是有问题的。HashMap底层是一个Entry数组当发生hash冲突的时候HashMap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点,对链表而言新加入的节点会从头结点加入,假如A线程和B线程同时对同一个数组位置进行添加数据,两个线程会同时得到现在的头结点,然后A写入新的头结点之后B也写入新的头结点,那B的写入操作就会覆盖A的写入操作造成A的写入操作丢失
ThreadLocal方式实现
public class ThreadExample6 { private static ThreadLocal<Integer> x = new ThreadLocal<Integer>(); public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { int data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " has put data :" + data); x.set(data); new A().get(); new B().get(); } }).start(); } } static class A { public void get() { int data = x.get(); System.out.println("A from " + Thread.currentThread().getName() + " get data :" + data); } } static class B { public void get() { int data = x.get(); System.out.println("B from " + Thread.currentThread().getName() + " get data :" + data); } } }
以上存在的问题:一个ThreadLocal只能放一个数据,如果你有两个变量要线程范围内共享,则要定义两个ThreadLocal。如下为解决方案:
public class ThreadExample7 { public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { int data = new Random().nextInt(); MyThreadScopeData.getThreadInstance().setName("name:名字" + data); MyThreadScopeData.getThreadInstance().setAge(data); new A().get(); new B().get(); } }).start(); } } static class A { public void get() { MyThreadScopeData myData = MyThreadScopeData.getThreadInstance(); System.out.println("A from " + Thread.currentThread().getName() + " getMyData: " + myData.getName() + "," + myData.getAge()); } } static class B { public void get() { MyThreadScopeData myData = MyThreadScopeData.getThreadInstance(); System.out.println("B from " + Thread.currentThread().getName() + " getMyData: " + myData.getName() + "," + myData.getAge()); } } } class MyThreadScopeData { private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>(); private MyThreadScopeData() { } public static synchronized MyThreadScopeData getThreadInstance() { MyThreadScopeData instance = map.get(); if (instance == null) { instance = new MyThreadScopeData(); map.set(instance); } return instance; } private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
此处解决的方式是用一个对象封装需要线程共享的对象,然后再把该对象绑定到ThreadLocal中, 实现线程范围内变量共享。对构造方法进行私有化并且getThreadInstance()进行同步,目的是确保整个线程只有一个MyThreadScopeData实例
相关文章推荐
- 【Java多线程与并发库】05 线程范围内共享变量ThreadLocal
- Java多线程——线程范围内共享变量和ThreadLocal
- 六:java中线程范围内共享变量--ThreadLocal
- 线程范围内共享变量使用ThreadLocal类详细方法
- 05_张孝祥_Java多线程_线程范围内共享变量的概念与作用
- java并发-多线程之线程范围内共享变量(5)
- Java线程总结(四):ThreadLocal实现线程范围的共享变量
- 使用JDK提供的ThreadLocal实现线程范围的共享变量(类似于Map<Thread,Variable>)
- android 线程范围内共享变量以及ThreadLocal的使用
- Java基础:多线程之线程范围内的数据共享ThreadLocal
- java多线程:线程范围内共享变量(四)
- 张孝祥java多线程视频笔记----线程范围内共享变量
- java多线程:5、线程范围内的数据共享_ThreadLocal
- java多线程之线程范围内共享变量的概念与作用
- java多线程模式ThreadLocal原理简述及其使用详解
- ThreadLocal实现线程范围内共享变量
- ThreadLocal实现:java线程范围内的共享数据,线程外独立
- (5)ThreadLocal类及应用技巧---- 线程范围内共享变量
- 黑马程序员--javaSE--ThreadLocal实现线程范围的共享变量
- Java线程(二):线程数据共享及ThreadLocal使用