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

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

2013-04-22 13:37 375 查看
ThreadLocal可以很方便的实现线程范围内的共享变量,ThreadLocal类就相当于一个Map。下面具体看这个类如何使用:

1-1 利用ThreadLocal实现线程范围内的共享变量

import java.util.Hashtable;
import java.util.Map;
import java.util.Random;
/*
每个线程拥有自己独立的数据
一个ThreadLocal代表一个变量,故其中只能放一个数据。
*/
public class ThreadLocalTest {//三个模块中的一个;
private static ThreadLocal<Integer> x=new ThreadLocal<Integer>();//x变量名
//ThreadLocal里边存放MyThreadScopeData数据
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() {
@Override
public void run() {
int data=new Random().nextInt();
System.out.println(Thread.currentThread().getName()
+"has put data :"+data);
x.set(data);//往当前线程中放数据,与当前线程相关的,不是全局的
MyThreadScopeData myData=new MyThreadScopeData();//new一个对象MyThreadScopeData()
myData.setName("name"+data);//往myData里边存放数据
myData.setAge(data);
MyThreadScopeData.set(myData);//存数据
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);
MyThreadScopeData myData=MyThreadScopeData.get();//取数据,包括name和age
System.out.println("A from "+Thread.currentThread().getName()
+"getmyData :"+myData.getName()+","+
myData.getAge());
}
}

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

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;
}
}


程序运行的结果如下:





上面的代码的整体思路:创建一个对象——放数据——取数据。代码组织的相当的糟糕,有没有一种优雅的实现实现方面呢?看下面的代码.

对代码1-1的改善,实现线程范围内的共享变量

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ThreadLocalTest {
private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
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(){
@Override
public void run() {
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()
+ " has put data :" + data);
x.set(data);
//得到与本线程有关的实力对象,在设置值
MyThreadScopeData.getThreadInstance().setName("name" + data);
MyThreadScopeData.getThreadInstance().setAge(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);
MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();//得到与本线程有关的实例对象,在设置值
System.out.println("A from " + Thread.currentThread().getName()
+ " getMyData: " + myData.getName() + "," +
myData.getAge());
}
}

static class B{
public void get(){
int data = x.get();
System.out.println("B from " + Thread.currentThread().getName()
+ " get data :" + data);
MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();//得到与本线程有关的实例对象,在设置值
System.out.println("B from " + Thread.currentThread().getName()
+ " getMyData: " + myData.getName() + "," +
myData.getAge());
}
}
}

class MyThreadScopeData{//将实体转化成单例
private MyThreadScopeData(){}//第一件事:构造方法私有化,让其它的没法创建它的实例对象
public static /*synchronized*/ MyThreadScopeData getThreadInstance(){
//利用静态方法,得到实例对象,synchronized时,在饥汉模式下
MyThreadScopeData instance = map.get();
if(instance == null){//饥汉模式,只有第一次时创建(需要的时候创建),以后直接饭回instance
instance = new MyThreadScopeData();//注意饥汉模式下,可能第一个线程来
//检查instance == null,就去创建(赋值),还没有返回的时候,CPU切换到第二个线程,第二个线程来检查,
//创建(赋值),那么可能就出现,第二次赋值覆盖第一次赋值,所以要互斥synchronized
map.set(instance);//将值存起来
}
return instance;//返回实例对象
}
//private static MyThreadScopeData instance = new MyThreadScopeData();//饱汉模式
//private static MyThreadScopeData instance = null;//饥汉模式
//装线程范围内的共享变量
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;
}
}

程序运行的结果:





每一请求(每一个线程),有一个容器对象,这个容器对象存放与这个请求有关的所有数据,struts2中会有这种思想。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 共享数据