关于ThreadLocal的初步理解

来源:互联网 发布:明朝朝鲜知乎 编辑:程序博客网 时间:2024/04/30 10:03
package com.joker.threads.demo.thread.mainsub;


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


/**
 * 
 * @author 线程范围内的数据共享如果不加map,则大家公用一个数据,而加入map,则避免这个情况出现
 *         1最原始的写法,用hashMap
 *         2用ThreadLocal
 *         ,ThreadLocal本身在存取的时候,使用的就是当前线程来存取的。一个ThreadLocal只能存储一个变量,
 *         而如果需要共享多个变量,那么可以自定义一个变量来存储对个变量,比如USER下可以放age,name......
 * 
 */
public class ThreadLocalDemo {
public static int count;
public static HashMap<String, Integer> data = new HashMap<String, Integer>();
public static ThreadLocal<Integer> local = new ThreadLocal<Integer>();


/**

* 用hashMap实现的线程范围的数据共享
*/
public static void changeCountByMap(int c) {
String threadName = Thread.currentThread().getName();
int d = 0;
if (null == data.get(threadName)) {
d = c;
} else {
d = data.get(threadName) + c;
}
data.put(threadName, d);
System.out.println(Thread.currentThread().getName() + "addCount:"
+ data.get(Thread.currentThread().getName()));
}


public static void changCountByThreadLocal(int c) {
String threadName = Thread.currentThread().getName();
int d = 0;
if (null == local.get()) {
d = c;
} else {
d = local.get() + c;
}
local.set(d);
System.out.println(Thread.currentThread().getName()
+ "afterChangeCount:" + local.get());
}


public static void changeUser(final String name,final int age) {
System.out.println(Thread.currentThread().getName()+":进行shoWUser操作");
User.getInstance().setName(name);
User.getInstance().setAge(age);
}
public static void shoWUser() {
System.out.println(Thread.currentThread().getName()+":进行shoWUser操作:NAME:"+User.getInstance().getName());
System.out.println(Thread.currentThread().getName()+":进行shoWUser操作:AGE:"+User.getInstance().getAge());
}




public static void main(String[] args) {
/**
* 测试MAP和ThreadLocal对单一属性的用法
* 10条线程,每条线程结果过永远等于0,而不会互相影响。
*/
for (int i = 0; i < 10; i++) {
new Thread() {
@Override
public void run() {
int c = new Random().nextInt(100);
// changeCountByMap(c);
// changeCountByMap(-c);
changCountByThreadLocal(c);
changCountByThreadLocal(-c);
}
}.start();
}
/**
* 测试对封装对象的ThreadLocal

*/
// new Thread() {
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName()+"开始启动");
// changeUser("123", 1);
// shoWUser();
// }
// }.start();
// new Thread() {
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName()+"开始启动");
// changeUser("456", 2);
// shoWUser();
// }
// }.start();
}

}
/**
 * 
 * 将ThreadlLocal放在user类中,而外部调用的时候只需要调用getInstance方法,
 * 类似于单例,外部不需要考虑线程数据共享的问题,获得的都是只属于本线程的单例
 */
 class User {
private static ThreadLocal<User> local = new ThreadLocal<User>(); 
public static User getInstance(){
User user = local.get();
if(null==user){
user = new User();
local.set(user);
}
return user;

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就是对每个线程都存储的Map,每个线程单独只操作的只属于该线程的资源。

 测试MAP和ThreadLocal对单一属性的用法:运行截图如下:

Thread-0afterChangeCount:27
Thread-5afterChangeCount:96
Thread-5afterChangeCount:0
Thread-3afterChangeCount:6
Thread-3afterChangeCount:0
Thread-1afterChangeCount:46
Thread-1afterChangeCount:0
Thread-0afterChangeCount:0
Thread-7afterChangeCount:92
Thread-2afterChangeCount:35
Thread-7afterChangeCount:0
Thread-2afterChangeCount:0
Thread-9afterChangeCount:7
Thread-9afterChangeCount:0
Thread-8afterChangeCount:23
Thread-4afterChangeCount:47
Thread-6afterChangeCount:13
Thread-6afterChangeCount:0
Thread-4afterChangeCount:0
Thread-8afterChangeCount:0

如Thread0 的运行结果。

0 0
原创粉丝点击