ThreadLocal是java中提供的一种维护变量的工具,尤其是一些需要维护的共享的静态变量。当多个线程访问同一个对象实例时,由于对象的引用特性,不同线程对该对象的增改都会影响其他线程的使用。这里就牵扯到多线程的共享与资源争夺问题。
ThreadLocal为每个访问线程提供了一个私有的变量存储空间,原理就是,依靠ThreadLocal实现了一个同步的map集合。集合中,键值对分别为线程的名字和访问的资源,是一对多的关系。
实例:
主函数:
public class LoggerTest {
public static void main(String[] args) throws Exception{
new TestThread("Thread1").start();//三个相同的线程
new TestThread("Thread2").start();//访问同一个静态变量
new TestThread("Thread3").start();//为了互不影响的操纵这个静态变量
}
}
公共线程:
class TestThread extends Thread{
public TestThread(String name) throws IOException {
super(name);
}
@Override
public void run() {
for (int i=0;i<10;i++){
SimpleThreadLogger.log(getName() +":message "); //三个线程调用同一个静态函数《==》访问公共资源
try{
Thread.sleep(1000);
}catch (Exception e){
SimpleThreadLogger.log(e.toString());
}
}
}
}
公共变量:
public class SimpleThreadLogger {
//三个线程都拥有这个静态变量,为了让他们不会互相影响
private static final java.lang.ThreadLocal<Logger> threadLocal1 =
new java.lang.ThreadLocal<Logger>();
//输出信息
public static void log(String msg){
getThreadLogger().log(Level.INFO, msg);
}
//根据线程取得专属Logger
private static Logger getThreadLogger(){
Logger logger = threadLocal1.get();
if(logger == null){
try{
logger = Logger.getLogger(
Thread.currentThread().getName()
);
//Logger 默认在控制台输出
//加入一个文件输出的handler
//它会输出xml的记录文件
logger.addHandler(
new FileHandler(
Thread.currentThread().getName() + ".log"));
}catch (IOException e){}
threadLocal1.set(logger);
}
return logger;
}
}
下面给出ThreadLocal实现的一个例子:
public class ThreadLocal<T>{
//一个带锁的同步集合
private Map<Thread,T> storage =
Collections.synchronizedMap(new HashMap<Thread, T>());
public T get(){
Thread current = Thread.currentThread();
T t = storage.get(current);
if(t==null && !storage.containsKey(current)){
t = initialValue();
storage.put(current,t);
}
return t;
}
public void set(T t){
storage.put(Thread.currentThread(), t);
}
public T initialValue(){
return null;
}
}