import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ThreadScopeShareData {
/**
* 多个线程访问同一个成员变量,因该是每一个线程拿到的变量是不同的
* 比如银行的转账
* 张三对李四
* 王五对赵六
* 如果成员变量不和线程绑定那么王五就可能在转账时操作张三的钱
* 如下程序因该是每个getData都要从自己的线程拿到自己的数据
* 然而实际情况并非如此
*/
// public static void main(String[] args) {
//
// for(int i=0;i<9;i++){
// new Thread(new Runnable(){
// @Override
// public void run() {
// int data = new Random().nextInt();
// System.out.println(Thread.currentThread().getName()+" has put data of " + data);
// new A().getData();
// new B().getData();
// }
//
// }).start();
// }
//
// }
//
// static class A{
// void getData(){
// System.out.println("A thread from "+Thread.currentThread().getName()+" get data of " + data);
// }
// }
//
// static class B{
// void getData(){
// System.out.println("B thread from "+Thread.currentThread().getName()+" get data of " + data);
//
// }
// }
/*
* 我们知道一个线程就对应一个数据,这就相当于map的key和value
* 把每个线程和对应的值填入一个map
* 下面就是一种解决方法
*/
// private static Map<Thread, Integer> dataMap = new HashMap<Thread, Integer>();
// public static void main(String[] args) {
//
// for(int i=0;i<9;i++){
// new Thread(new Runnable(){
// @Override
// public void run() {
// int data = new Random().nextInt();
// dataMap.put(Thread.currentThread(),data);
// System.out.println(Thread.currentThread().getName()+" has put data of " + data);
// new A().getData();
// new B().getData();
// }
//
// }).start();
// }
//
// }
//
// static class A{
// void getData(){
// int data = dataMap.get(Thread.currentThread());
// System.out.println("A thread from "+Thread.currentThread().getName()+" get data of " + data);
// }
// }
//
// static class B{
// void getData(){
// int data = dataMap.get(Thread.currentThread());
// System.out.println("B thread from "+Thread.currentThread().getName()+" get data of " + data);
//
// }
// }
// /*
// * java也提供了一个类来控制线程和变量之间的绑定:ThreadLocal
// * ThreadLocal就相当于上例的map
// */
//
// private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
// public static void main(String[] args) {
//
// for(int i=0;i<9;i++){
// new Thread(new Runnable(){
// @Override
// public void run() {
// int data = new Random().nextInt();
////调用threadLocal.set();参数是要保存的数字
// threadLocal.set(data);
// System.out.println(Thread.currentThread().getName()+" has put data of " + data);
// new A().getData();
// new B().getData();
// }
//
// }).start();
// }
//
// }
//
// static class A{
// void getData(){
////threadLocal.get()不用指定当前线程,他代表的就是当前线程
// int data = threadLocal.get();
// System.out.println("A thread from "+Thread.currentThread().getName()+" get data of " + data);
// }
// }
//
// static class B{
// void getData(){
////threadLocal.get()不用指定当前线程,他代表的就是当前线程
// int data = threadLocal.get();
// System.out.println("B thread from "+Thread.currentThread().getName()+" get data of " + data);
//
// }
// }
//
// /*
// * 总结:一个threadLocal代表一个变量,故其中只能放一个数据,如果有两个变量要线程共享
// * 则要定义两个ThreadLocal对象,如果有很多的变量要共享,就可以考虑把这些变量封装
// * 然后在ThreadLocal中存储这个对象
// * 下面示例是多个变量
// */
/*
* 一个线程和多个变量之间的绑定
*/
//
// private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
// private static ThreadLocal<MyThreadScopeData> myThreadLocal = new ThreadLocal<MyThreadScopeData>();
// public static void main(String[] args) {
//
// for(int i=0;i<9;i++){
// new Thread(new Runnable(){
// @Override
// public void run() {
// int data = new Random().nextInt();
// threadLocal.set(data);
// System.out.println(Thread.currentThread().getName()+" has put data of " + data);
//
////
// MyThreadScopeData myData = new MyThreadScopeData();
// myData.setName("name" + data);
// myData.setAge(data);
// myThreadLocal.set(myData);
//
// new A().getData();
// new B().getData();
// }
//
// }).start();
// }
//
// }
//
// static class A{
// void getData(){
// int data = threadLocal.get();
// System.out.println("A thread from "+Thread.currentThread().getName()+" get data " + data);
//
// MyThreadScopeData myData = myThreadLocal.get();
// System.out.println("A thread from "+Thread.currentThread().getName()+" get data " + myData.getAge() + " , " +myData.getAge());
// }
// }
//
// static class B{
// void getData(){
// int data = threadLocal.get();
// System.out.println("B thread from "+Thread.currentThread().getName()+" get data " + data);
//
// MyThreadScopeData myData = myThreadLocal.get();
// System.out.println("B thread from "+Thread.currentThread().getName()+" get data " + myData.getAge() + " , " +myData.getAge());
//
// }
// }
//
// /*
// * 首先定义一个类封装数据
// */
// static 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;
// }
// }
//一种更为优雅的实现方式,可以隐藏ThreadLocal
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
public static void main(String[] args) {
for(int i=0;i<9;i++){
new Thread(new Runnable(){
@Override
public void run() {
int data = new Random().nextInt();
threadLocal.set(data);
System.out.println(Thread.currentThread().getName()+" has put data of " + data);
MyThreadScopeData.getInstance().setName("name is "+data);
MyThreadScopeData.getInstance().setAge(data);
new A().getData();
new B().getData();
}
}).start();
}
}
static class A{
void getData(){
int data = threadLocal.get();
System.out.println("A thread from "+Thread.currentThread().getName()+" get data " + data);
MyThreadScopeData myData = MyThreadScopeData.getInstance();
System.out.println("A thread from "+Thread.currentThread().getName()+" get data " + myData.getAge() + " , " +myData.getAge());
}
}
static class B{
void getData(){
int data = threadLocal.get();
System.out.println("B thread from "+Thread.currentThread().getName()+" get data " + data);
MyThreadScopeData myData = MyThreadScopeData.getInstance();
System.out.println("B thread from "+Thread.currentThread().getName()+" get data " + myData.getAge() + " , " +myData.getAge());
}
}
/*
* 实现这个类的单例
*/
static class MyThreadScopeData{
/*饱汉模式创建单例
private MyThreadScopeData(){}
private static MyThreadScopeData instance = new MyThreadScopeData();
public synchronized MyThreadScopeData getInstance(){
return instance;
}
*/
/* 饥汉模式创建单例
private MyThreadScopeData(){}
private static MyThreadScopeData instance = null;
public synchronized MyThreadScopeData getInstance(){
if(instance == null){
instance = new MyThreadScopeData();
}
return instance;
}
*/
//将ThreadLocal放在了单例的实现里,外部就不用了解内部的实现,外部的调用自然就是与线程有关的实例
private MyThreadScopeData(){}
// private static MyThreadScopeData instance = null;
private static ThreadLocal<MyThreadScopeData> local = new ThreadLocal<MyThreadScopeData>();
public static /*synchronized就可以不用了*/ MyThreadScopeData getInstance(){
MyThreadScopeData instance= local.get();
if(instance == null){
instance = new MyThreadScopeData();
local.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;
}
}
}