【Java多线程与并发库】6.ThreadLocal类及应用技巧
2016-10-12 09:52
639 查看
之前我们了解了实现线程范围内数据共享的机制,接下来我们
可以使用JDK5提供的ThreadLocal类,来实现线程范围内数据共享。
ThreadLocal类其实就类似于我们上一次创建的Map。
我们创建一个测试类,来使用ThreadLocal类实现线程范围内数据共享:
我们的类A和类B每次都从线程中获取data值打印,为了保证每次打印的数据是该线程的数据,
类A和类B的数据都从ThreadLocal中获取。
结果:
实现了每个线程中的数据共享在每个线程自己的范围内。线程之间的数据不会混杂在一起。
如果有N个变量需要做到线程范围内数据共享,应该如何做到?
一个ThreadLocal只能放一个变量,我们可以使用多个ThreadLocal来实现,
如果共享的数据量过大,我们就把这些数据放在一个对象中,然后在ThreadLocal中
存储这一个对象。
结果:
这样就可以在线程范围内共享N中数据了。
上面的设计其实不够好,但是要设计更加优雅一点,不要看到我们使用ThreadLocal的痕迹:
这里,我们调用MyThreadScopeData的getThreadInstance方法,就可以取得
与当前线程相关的实例对象。
虽然线程结束后也可以自动释放相关的ThreadLocal变量,但是为了优化内存,
我们的ThreadLocal要在线程结束的时候注销,可以调用ThreadLocal.clear()方法。
转载请注明出处:http://blog.csdn.net/acmman/article/details/52794523
可以使用JDK5提供的ThreadLocal类,来实现线程范围内数据共享。
ThreadLocal类其实就类似于我们上一次创建的Map。
我们创建一个测试类,来使用ThreadLocal类实现线程范围内数据共享:
我们的类A和类B每次都从线程中获取data值打印,为了保证每次打印的数据是该线程的数据,
类A和类B的数据都从ThreadLocal中获取。
package cn.edu.hpu.test; import java.util.Random; public class ThreadTest7 { private static Random dandom=new Random(); 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(){ public void run() { int data=dandom.nextInt(); System.out.println(Thread.currentThread().getName() +"放入数据:"+data); x.set(data); new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ System.out.println("A 从"+Thread.currentThread().getName() +"中取的数据:"+x.get()); } } static class B{ public void get(){ System.out.println("B 从"+Thread.currentThread().getName() +"中取的数据:"+x.get()); } } }
结果:
实现了每个线程中的数据共享在每个线程自己的范围内。线程之间的数据不会混杂在一起。
如果有N个变量需要做到线程范围内数据共享,应该如何做到?
一个ThreadLocal只能放一个变量,我们可以使用多个ThreadLocal来实现,
如果共享的数据量过大,我们就把这些数据放在一个对象中,然后在ThreadLocal中
存储这一个对象。
package cn.edu.hpu.test; import java.util.Random; public class ThreadTest7 { private static Random dandom=new Random(); private static ThreadLocal<MyThreadScopeData> MyThreadScopeData=new ThreadLocal<MyThreadScopeData>(); public static void main(String[] args) { for(int i=0;i<2;i++){ new Thread(new Runnable(){ public void run() { int data=dandom.nextInt(); System.out.println(Thread.currentThread().getName() +"放入数据:"+data); MyThreadScopeData ScopeData=new MyThreadScopeData(); ScopeData.setName("name"+data); ScopeData.setAge(data); MyThreadScopeData.set(ScopeData); new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ System.out.println("A 从"+Thread.currentThread().getName() +"中取的数据:"+MyThreadScopeData.get().getName() +MyThreadScopeData.get().getAge()); } } static class B{ public void get(){ System.out.println("A 从"+Thread.currentThread().getName() +"中取的数据:"+MyThreadScopeData.get().getName() +MyThreadScopeData.get().getAge()); } } } class MyThreadScopeData{ 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; } }
结果:
这样就可以在线程范围内共享N中数据了。
上面的设计其实不够好,但是要设计更加优雅一点,不要看到我们使用ThreadLocal的痕迹:
package cn.edu.hpu.test; import java.util.Random; public class ThreadTest7 { private static Random dandom=new Random(); public static void main(String[] args) { for(int i=0;i<2;i++){ new Thread(new Runnable(){ public void run() { int data=dandom.nextInt(); System.out.println(Thread.currentThread().getName() +"放入数据:"+data); MyThreadScopeData.getThreadInstance().setName("name"+data); MyThreadScopeData.getThreadInstance().setAge(data); new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ System.out.println("A 从"+Thread.currentThread().getName() +"中取的数据:"+MyThreadScopeData.getThreadInstance().getName() +MyThreadScopeData.getThreadInstance().getAge()); } } static class B{ public void get(){ System.out.println("A 从"+Thread.currentThread().getName() +"中取的数据:"+MyThreadScopeData.getThreadInstance().getName() +MyThreadScopeData.getThreadInstance().getAge()); } } } class MyThreadScopeData{ private MyThreadScopeData(){} public static MyThreadScopeData getThreadInstance(){ MyThreadScopeData instance=map.get(); if(instance==null){ instance=new MyThreadScopeData(); map.set(instance); } return instance; } private static ThreadLocal<MyThreadScopeData> map =new ThreadLocal<MyThreadScopeData>(); 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; } }
这里,我们调用MyThreadScopeData的getThreadInstance方法,就可以取得
与当前线程相关的实例对象。
虽然线程结束后也可以自动释放相关的ThreadLocal变量,但是为了优化内存,
我们的ThreadLocal要在线程结束的时候注销,可以调用ThreadLocal.clear()方法。
转载请注明出处:http://blog.csdn.net/acmman/article/details/52794523
相关文章推荐
- 【Java多线程与并发库】6.ThreadLocal类及应用技巧
- 【java并发】ThreadLocal类以及应用技巧
- Java并发06---ThreadLocal类以及应用技巧
- Java并发06---ThreadLocal类以及应用技巧
- 多线程并发库高级应用 之 java5中的线程并发库--线程锁技术
- 多线程并发库高级应用 之 java5中的线程并发库--线程池、Callable&Future
- 多线程并发库高级应用 之 java5中的线程并发库--线程锁技术
- Java多线程与并发库高级应用
- Java多线程与并发库高级应用之阻塞队列BlockingQueue
- 探索并发编程(五)------Java多线程开发技巧
- Java多线程与并发库高级应用之Callable和Future
- (13)多线程与并发库之java5阻塞队列(BlockingQueue)的应用----子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程循环100次,如此循环50次
- (14)多线程与并发库之java5同步集合类的应用【包含jdk1.5新特性 ConcurrentHashMap】
- Java多线程与并发库高级应用之信号量Semaphore
- Java多线程下 ThreadLocal 的应用实例
- java高级进阶关于java多线程的应用 ThreadLocal多线程实例详解
- (14)多线程与并发库之java5同步集合类的应用【包含jdk1.5新特性 ConcurrentHashMap】
- Java多线程与并发库高级应用之线程池
- (13)多线程与并发库之java5阻塞队列(BlockingQueue)的应用----子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程循环100次,如此循环50次
- 多线程并发库高级应用 之 使用java5中同步技术的3个面试题