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

Java中如何实现单个线程范围内的数据共享

2014-05-01 16:10 886 查看
单个线程范围内的数据共享,就是确保当前的线程在执行的过程中,各个模块所引用的数据是一份,且所引用的数据不会因为其他线程的操作而变化。

以下是一段没有达到线程内数据共享的代码(参考自传智播客视频)

public class ThreadScopeShareData
{
//用于存放随机产生的数据
static int data = 0;
public static void main(String[] args)
{
//线程1
new Thread(new Runnable()
{
@Override
public void run()
{
data = new Random().nextInt(1000);
System.out.println(Thread.currentThread().getName()
+ "has put data:" + data);
//使用A对象输出数据
new A().getData();
//使用B对象输出数据
new B().getData();
}
}).start();

//线程2
new Thread(new Runnable()
{
@Override
public void run()
{
data = new Random().nextInt(1000);
System.out.println(Thread.currentThread().getName()
+ "has put data:" + data);
//使用A对象输出数据
new A().getData();
//使用B对象输出数据
new B().getData();
}
}).start();
}
}

class A
{
public void getData()
{
System.out.println("A :" + Thread.currentThread().getName()
+ ": get data value:" + ThreadScopeShareData.data);
}
}

class B
{
public void getData()
{
System.out.println("B :" + Thread.currentThread().getName()
+ ": get data value:" + ThreadScopeShareData.data);
}
}


控制台输出:



根据控制台的结果,可以看出,由于定义了static的变量存储数据,那么当线程2更改了data数据后,线程1中 A模块和B模块取出的和当初线程1放入的不是一个值,如何解决这个问题呢?见如下代码:

一、使用全局的map变量实现

public class ThreadScopeShareData
{
//用于存放随机产生的数据
//static int data = 0;
/*
* 使用map类型的变量取代int类型的变量
*/
static Map<Thread, Integer> map = new HashMap<Thread, Integer>();
public static void main(String[] args)
{
//线程1
new Thread(new Runnable()
{
@Override
public void run()
{
//data = new Random().nextInt(1000);
int data = new Random().nextInt(1000);
//用当前线程作为key,将当前线程产生的随机数,存入map中
map.put(Thread.currentThread(), data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A对象输出数据
new A().getData();
//使用B对象输出数据
new B().getData();
}
}).start();

//线程2
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//用当前线程作为key,将当前线程产生的随机数,存入map中
map.put(Thread.currentThread(), data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A对象输出数据
new A().getData();
//使用B对象输出数据
new B().getData();
}
}).start();
}
}

class A
{
public void getData()
{
//使用当前线程作为map的key去取出map中对应的value
System.out.println("A :" + Thread.currentThread().getName()
+ ": get data value:"
+ ThreadScopeShareData.map.get(Thread.currentThread()));
}
}

class B
{
public void getData()
{
//使用当前线程作为map的key去取出map中对应的value
System.out.println("B :" + Thread.currentThread().getName()
+ ": get data value:"
+ ThreadScopeShareData.map.get(Thread.currentThread()));
}
}


二、使用ThreadLocal类,实现单个线程范围内 单个变量的数据共享

public class ThreadScopeShareData
{
/*
* 使用ThreadLocal
*/
static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
public static void main(String[] args)
{
//线程1
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//将当前线程产生的随机数,存入threadLocal中
threadLocal.set(data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A对象输出数据
new A().getData();
//使用B对象输出数据
new B().getData();
}
}).start();

//线程2
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//将当前线程产生的随机数,存入threadLocal中
threadLocal.set(data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A对象输出数据
new A().getData();
//使用B对象输出数据
new B().getData();
}
}).start();
}
}

class A
{
public void getData()
{
//从threadLocal中取出value
System.out.println("A :" + Thread.currentThread().getName()
+ ": get data value:"
+ ThreadScopeShareData.threadLocal.get());
}
}

class B
{
public void getData()
{
//从threadLocal中取出value
System.out.println("B :" + Thread.currentThread().getName()
+ ": get data value:"
+ ThreadScopeShareData.threadLocal.get());
}
}


三、使用ThreadLocal实现 单个线程内 多个变量的数据共享

实现多个数据的共享可以使用Map去存放数据,这里就不说了 就是把ThreadLocal中的Integer替换成Map即可,主要贴一下使用对象存储多个变量的代码实现

①创建一个用于存放共享数据的类

/**
* 存放共享数据的对象
* @author ***
*
*/
class ShareDataObj
{
/**
* threadLocal
*/
private static ThreadLocal<ShareDataObj> threadLocal =
new ThreadLocal<ShareDataObj>();

private ShareDataObj()
{
}

/**
* 返回从ThreadLocal中取出当前线程的ShareDataObj对象
* @return
*/
public static ShareDataObj getInstance4currentThread()
{
//从threadLocal变量中取出当前线程的ShareDataObj对象
ShareDataObj dataObj = threadLocal.get();
if(dataObj == null)
{
//1、创建一个新的对象
dataObj = new ShareDataObj();
//2、将创建的对象放入ShareDataObj对象中
threadLocal.set(dataObj);
}

return dataObj;
}

//data1
private int data1;
//data2
private String data2;

public int getData1()
{
return data1;
}

public void setData1(int data1)
{
this.data1 = data1;
}

public String getData2()
{
return data2;
}

public void setData2(String data2)
{
this.data2 = data2;
}
}


②操作共享数据

public class ThreadScopeShareData
{
public static void main(String[] args)
{
//线程1
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//将当前线程产生的随机数,放入数据共享对象中
ShareDataObj.getInstance4currentThread().setData1(data);
ShareDataObj.getInstance4currentThread().setData2("str-" + data);

System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A对象输出数据
new A().getData();
//使用B对象输出数据
new B().getData();
}
}).start();

//线程2
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//将当前线程产生的随机数,放入数据共享对象中
ShareDataObj.getInstance4currentThread().setData1(data);
ShareDataObj.getInstance4currentThread().setData2("str-" + data);

System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A对象输出数据
new A().getData();
//使用B对象输出数据
new B().getData();
}
}).start();
}
}

class A
{
public void getData()
{
//从ShareDataObj中取出当前线程的数据共享对象
System.out.println("A :" + Thread.currentThread().getName()
+ ": get data1:"
+ ShareDataObj.getInstance4currentThread().getData1()
+ ", get data2:"
+ ShareDataObj.getInstance4currentThread().getData2());
}
}

class B
{
public void getData()
{
//从ShareDataObj中取出当前线程的数据共享对象
System.out.println("B :" + Thread.currentThread().getName()
+ ": get data1:"
+ ShareDataObj.getInstance4currentThread().getData1()
+ ", get data2:"
+ ShareDataObj.getInstance4currentThread().getData2());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: