直接聊技术!
描述
ThreadLocal直译为 本地线程,但是实际意思却不是这样的,它是一个容器,用于存放本地线程的局部变量,到底为什么叫ThreadLocal,讲道理,我也不知道!
业务描述 在一个类中调用三个线程,三个线程分别进行报数1、2、3
/** * @author:稀饭 * @time:下午8:10:59 * @filename:Sequence.java */package demo;public interface Sequence { public int getNumber();}/** * @author:稀饭 * @time:下午8:12:24 * @filename:ClientThread.java */package demo;public class ClientThread extends Thread { PRivate Sequence sequence; public ClientThread(Sequence sequence) { // TODO Auto-generated constructor stub this.sequence = sequence; } /** * @Title: run * @Description: TODO */ @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + " ==> " + sequence.getNumber()); } }}/** * @author:稀饭 * @time:下午8:18:27 * @filename:TestA.java */package demo;public class TestA implements Sequence { private static int number = 0; @Override public int getNumber() { // TODO Auto-generated method stub number = number + 1; return number; } public static void main(String[] args) { Sequence sequence = new TestA(); ClientThread clientThread1 = new ClientThread(sequence); ClientThread clientThread2 = new ClientThread(sequence); ClientThread clientThread3 = new ClientThread(sequence); clientThread1.start(); clientThread2.start(); clientThread3.start(); }}运行结果如下: Thread-0 ==> 1 Thread-2 ==> 3 Thread-1 ==> 2 Thread-2 ==> 5 Thread-0 ==> 4 Thread-2 ==> 7 Thread-1 ==> 6 Thread-0 ==> 8 Thread-1 ==> 9
**源码分析:**Thread没有按照先后顺序输出,这个可以理解,毕竟线程的启动是随机的,而为什么输出的结果不是1、2、3、1、2、3、1、2、3呢,仔细分析才发现,number是static的,是类所共享的,无法保证对不同线程来说是安全的,大家操作的都是同一个变量,当然一直在递增了。
那么如何做到各自线程递增这样的结果呢?
现在引入ThreadLocal,源码如下
/** * @author:稀饭 * @time:下午8:18:27 * @filename:TestA.java */package demo;public class TestB implements Sequence { private static ThreadLocal<Integer> container = new ThreadLocal<Integer>() { @Override protected Integer initialValue() { // TODO Auto-generated method stub return 0; } }; @Override public int getNumber() { // TODO Auto-generated method stub container.set(container.get() + 1); return container.get(); } public static void main(String[] args) { Sequence sequence = new TestB(); ClientThread clientThread1 = new ClientThread(sequence); ClientThread clientThread2 = new ClientThread(sequence); ClientThread clientThread3 = new ClientThread(sequence); clientThread1.start(); clientThread2.start(); clientThread3.start(); }}运行结果如下: Thread-0 ==> 1 Thread-1 ==> 1 Thread-2 ==> 1 Thread-1 ==> 2 Thread-0 ==> 2 Thread-1 ==> 3 Thread-2 ==> 2 Thread-0 ==> 3 Thread-2 ==> 3
源码解析:在TestA中引入ThreadLocal之后输出的结果变成了我上面说的那样,用了ThreadLocal之后每个线程独立了,虽然同样是static,但是线程独立了,也就是说ThreadLocal会为每一个不同的线程设置一个独立的副本。
现在才是最重要的地方,我们自己来实现一个ThreadLocal
先来分析一下ThreadLocal的api:
public void set(T vlue) 将值放入线程局部变量中 public T get() 从线程局部变量中获取 public void remove() 从线程局部中移除值 protected T initialValue() 返回线程局部变量中的初始值以下是我自己实现的ThreadLocal
源码分析:在源码中我使用了线程安全的Map也就是同步Map,目的是为了防止出现多线程出现的不安全问题。
Note:发布的这些文章全都是自己边学边总结的,难免有纰漏,如果发现有不足的地方,希望可以指出来,一起学习咯,么么哒。 开源爱好者,相信开源的力量必将改变世界: * osc :* https://git.oschina.net/xi_fan github: https://github.com/wiatingpub
新闻热点
疑难解答