线程安全,很好使的一种方法
java.lang.ThreadLocal的诞生就是为了解决多线程并发问题。
举例子
不使用ThreadLocal
不使用ThreadLocal实现并发,可以发现各个线程之间共享了number 变量,如果我不想共享,使得每个线程都独占该咋办呢。
interface Sequence{
int getNumber();
}
class ClientThread extends Thread{
private Sequence sequence;
public ClientThread(Sequence sequence){
this.sequence=sequence;
}
public void run(){
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+": "+sequence.getNumber());
}
}
}
public class ThreadLocal_Test implements Sequence{
private static int number=0;
public int getNumber(){
number+=1;
return number;
}
public static void main(String args[]){
Sequence sequence=new ThreadLocal_Test();
ClientThread one=new ClientThread(sequence);
ClientThread two=new ClientThread(sequence);
ClientThread three=new ClientThread(sequence);
one.start();
two.start();
three.start();
}
}
使用ThreadLocal
这样每个线程都能够独享自己的局部变量,这岂不是美滋滋
package Train;
interface Sequence{
int getNumber();
}
class ClientThread extends Thread{
private Sequence sequence;
public ClientThread(Sequence sequence){
this.sequence=sequence;
}
public void run(){
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+": "+sequence.getNumber());
}
}
}
public class ThreadLocal_Test implements Sequence{
private static ThreadLocal<Integer> numberContainer=new ThreadLocal<Integer>(){
protected Integer initialValue(){
return 0;
}
};
public int getNumber() {
numberContainer.set(numberContainer.get()+1);
return numberContainer.get();
}
public static void main(String args[]){
Sequence sequence=new ThreadLocal_Test();
ClientThread one=new ClientThread(sequence);
ClientThread two=new ClientThread(sequence);
ClientThread three=new ClientThread(sequence);
one.start();
two.start();
three.start();
}
}
再来看一下官方文档中ThreadLocal的API:
自己封装一个ThreadLocal
看完ThreadLocal的API后,发现也没有多难,不就是封装了一个Map,那就自己玩一下试试。
package Train;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
class MyThreadlocal<T> {
private Map<Thread,T> container= Collections.synchronizedMap(new HashMap<Thread, T>());
public void set(T value){
container.put(Thread.currentThread(),value);
}
public T get(){
Thread thread=Thread.currentThread();
T value=container.get(thread);
if(value==null&&!container.containsKey(thread)){
value=initalValue();
container.put(thread,value);
}
return value;
}
public void remove(){
container.remove(Thread.currentThread());
}
protected T initalValue(){
return null;
}
}
public class Test implements Sequence{
private static MyThreadlocal<Integer> numberContainer=new MyThreadlocal<Integer>(){
protected Integer initalValue(){
return 0;
}
};
@Override
public int getNumber() {
numberContainer.set(numberContainer.get()+1);
return numberContainer.get();
}
public static void main(String []args){
Sequence sequence=new Test();
ClientThread one =new ClientThread(sequence);
ClientThread two=new ClientThread(sequence);
ClientThread three=new ClientThread(sequence);
one.start();
two.start();
three.start();
}
}
还算合格,能用!
小结
ThreadLocal用处实在是太大了,最典型的就是高并发下的JDBC了,完美解决JDBC的线程安全问题!