简单的理解ThreadLocal

线程安全,很好使的一种方法

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的线程安全问题!

猜你喜欢

转载自blog.csdn.net/mikeoperfect/article/details/80621388