(三) Java多线程详解之线程范围内共享变量及ThreadLocal类使用
来源:互联网 发布:海信网络电视看新闻 编辑:程序博客网 时间:2024/06/05 11:08
1.在开发中经常会遇到一种情况:有一个变量会被多个线程访问,但是要确保同个线程内,访问的是同一个对象,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的写入操作丢失
2.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实例。
阅读全文
0 0
- (三) Java多线程详解之线程范围内共享变量及ThreadLocal类使用
- Java基础:多线程之线程范围内的数据共享ThreadLocal
- 线程范围内共享变量使用ThreadLocal类详细方法
- 多线程编程入门(8):线程范围内的共享变量之ThreadLocal
- 【Java多线程与并发库】05 线程范围内共享变量ThreadLocal
- android 线程范围内共享变量以及ThreadLocal的使用
- 六:java中线程范围内共享变量--ThreadLocal
- 多线程之线程范围内的数据共享ThreadLocal
- (5)ThreadLocal类及应用技巧---- 线程范围内共享变量
- (5)ThreadLocal类及应用技巧---- 线程范围内共享变量
- 线程范围内共享变量的概念与作用以及ThreadLocal类及应用修复bug
- ThreadLocal 线程范围内的共享变量
- ThreadLocal实现线程范围内共享变量
- ThreadLocal线程范围内的共享变量
- 线程范围内共享变量(ThreadLocal)
- ThreadLocal线程范围内的共享变量
- ThreadLocal实现线程范围内的共享变量
- 多线程(三) 实现线程范围内模块之间共享数据及线程间数据独立(ThreadLocal)
- wxWidgets编写自定义的控件
- Python-set(4)
- Java环境变量配置
- Spring配置之mybatis-configuration.xml
- hdoj 1018 Big Number (n!的数学公式 数学)
- (三) Java多线程详解之线程范围内共享变量及ThreadLocal类使用
- 李明linux教学视频----CH7.。。用户和用户组
- pythonTip
- 罗振宇与罗永浩的6小时长谈
- io流中的字节流
- 罗斯基白话:TensorFlow + 实战系列(五)实战MNIST
- c++primer学习笔记
- 带固定列支持横向滑动的ListView
- shell