ThreadLocal 本地线程,可以解决线程之前静态资源共享的问题,做到线程安全
直接上代码
定义一个接口
package org.blueskytoolkit.source.thread.threadlocal;
/**
* 序列化接口
* @author zw
* 2016年6月1日上午9:38:32
*/
public interface Sequence {
public int getNumber();
}
一个线程类 这里是继承的方式
package org.blueskytoolkit.source.thread.threadlocal;
public class ThreadDome extends Thread{
private Sequence sequence;
public ThreadDome(Sequence sequence) {
this.sequence = sequence;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " => " + sequence.getNumber());
}
}
}
把每个线程打印3次看看数据增长值
使用ThreadLocal类
package org.blueskytoolkit.source.thread.threadlocal;
public class ThreadDomeTest2 implements Sequence {
/**
* 每个线程相互独立了,同样是 static 变量,对于不同的线程而言,它没有被共享,
* 而是每个线程各一份,这样也就保证了线程安全。 也就是说,TheadLocal 为每一个线程提供了一个独立的副本
*
* 通过 ThreadLocal 封装了一个 Integer 类型的 numberContainer 静态成员变量,并且初始值是0。
* 再看 getNumber() 方法,首先从 numberContainer 中 get 出当前的值,加1,随后 set 到 numberContainer 中,最后将 numberContainer 中 get 出当前的值并返回
*/
private static ThreadLocal<Integer> numberContainer = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
public int getNumber() {
numberContainer.set(numberContainer.get() + 1);
return numberContainer.get();
}
/**
* public void set(T value):将值放入线程局部变量中
* public T get():从线程局部变量中获取值
* public void remove():从线程局部变量中移除值(有助于 JVM 垃圾回收)
* protected T initialValue():返回线程局部变量中的初始值(默认为 null)
* @param args
*/
public static void main(String[] args) {
Sequence sequence = new ThreadDomeTest2();
ThreadDome thread1 = new ThreadDome(sequence);
ThreadDome thread2 = new ThreadDome(sequence);
ThreadDome thread3 = new ThreadDome(sequence);
thread1.start();
thread2.start();
thread3.start();
}
}
输出结果,每个线程是单独的资源 数值不会随着其他线程而变化
这里自定义一个ThreadLocal类 实现主要的几个api即可
package org.blueskytoolkit.source.thread.threadlocal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* 自定义一个threadlocal
* 一个类中使用了 static 成员变量的时候,一定要多问问自己,这个 static 成员变量需要考虑“线程安全”吗?(也就是说,多个线程需要独享自己的 static 成员变量
* @author zw
* 2016年6月1日上午10:25:45
* @param <T>
*/
public class MyThreadLocal<T> {
/**
* 返回了一个线程安全的实现了 Map 接口的 实现类 HashMap 支持多线程数据的同步。保证多线程访问数据的一致性
*/
private Map<Thread, T> map = Collections
.synchronizedMap(new HashMap<Thread, T>());
public void set(T value) {
map.put(Thread.currentThread(), value);
}
//获取
public T get() {
Thread thread = Thread.currentThread();
T value = map.get(thread);
if (value == null && !map.containsKey(thread)) {
//拿到默认值
value = initialValue();
map.put(thread, value);
}
return value;
}
// 移除
public void remove() {
map.remove(Thread.currentThread());
}
//初始化
protected T initialValue() {
return null;
}
}