您的位置:首页 > 编程语言 > Java开发

Java线程范围内的共享数据(2)

2014-12-10 00:21 501 查看


实际上那么Map也就是模拟的ThreadLocal

每一个线程调用全局的ThreadLocal对象的set方法,就相当于往其内部的map记录新的键值对,键是Thread.current,值是data


线程结束后,可以选择调用ThreadLocal的clear()方法,释放内存,当某一个线程死掉后,可以用remove()移走

相关的变量,但是问题是,如何监听得知某个线程即将死亡?


ThreadDeadRequest事件,只说了一点,太含糊,求解惑?



import java.util.Random;

public class TreadLocalDemo {

private static int data = 0;
private static ThreadLocal<Integer> tc = 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 = new Random().nextInt();
System.out.println(Thread.currentThread().getName()+
" has put data: "+data);
tc.set(data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get(){
int data = tc.get();
System.out.println("A from "+Thread.currentThread().getName()+
" get data: "+data);
}

}
static class B{
public void get(){
int data = tc.get();
System.out.println("B from "+Thread.currentThread().getName()+
" get data: "+data);
}
}
}




应用场景:

比如在淘宝上提交订单,这一事件至少涉及:减少库存、修改总账,这几个操作要在同一事物上完成,一般也就是在


一个线程上完成,假如在修改总账的操作上失败了,那么前面的所有操作都必须撤销,回滚。如果没有问题,


那么就提交所有操作,
但是要求这些操作必须使用的是相同的数据库连接对象,这些操作的具体代码存储在不用的模块中
类似的同一事物操控的不同流水线操作,都是如此(银行转账)

从上述的两个例子可以看出:多个类在同一线程上共享同一份数据

PS:需要注意的一点是,一个ThreadLocal只能代表一个变量,有两个变量,就必须创建两个ThreadLocal,N个,那么就必须把这N个变量封装成对象,再用ThreadLocal存储这个对象




最终我们对外暴露的仅仅是这一个事物,而事物内部如何实现的数据共享,外部是不需要知道的



import java.util.Random;

class MyOperatorData{

private MyOperatorData(){}

public static /*synchronized*/ MyOperatorData getThreadInstance(){

MyOperatorData instance = mapLocal.get();

if(instance == null){
instance = new MyOperatorData();
mapLocal.set(instance);
}
return instance;
}
//private static MyOperatorData instance = null;
private static ThreadLocal<MyOperatorData> mapLocal = new ThreadLocal<MyOperatorData>();
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;
}

}
public class TreadLocalDemo {

public static void main(String[] args) {

for(int i = 0;i<2;i++){
new Thread(new Runnable() {
public void run() {
int data = new Random().nextInt();

System.out.println(Thread.currentThread().getName()+
" has put data: "+data);

MyOperatorData.getThreadInstance().setName("name"+data);

MyOperatorData.getThreadInstance().setAge(data);

new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get(){

MyOperatorData mydata = MyOperatorData.getThreadInstance();
System.out.println("A from "+Thread.currentThread().getName()+
" getMydata "+mydata.getName()+" , "+mydata.getAge());
}

}
static class B{
public void get(){

MyOperatorData mydata = MyOperatorData.getThreadInstance();
System.out.println("B from "+Thread.currentThread().getName()+
" getMydata "+mydata.getName()+" , "+mydata.getAge());
}
}
}


ThreadLocal类通常会用在一个类的成员上

当多个线程去访问这个类的时候,那么每个线程都有自己的副本,操作的是属于自己的那一份,互不干扰。

Class user {
private ThreadLocal<String> userName = new ThreadLocal<>();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: