ThreadLocal学习

来源:互联网 发布:node.js实战 pdf 下载 编辑:程序博客网 时间:2024/05/18 00:25

1.什么是ThreadLocal?

ThreadLocal是一个容器,用于存放线程的局部变量,用来保护线程安全的。

2.举例说明

比如设计一个序列号生成器,有多个线程同时并发的去访问,但是要保证每个线程得到的序列号都是自增的,并且互相不干扰?

3.代码实现方式

  • 1.先定义一个接口
package com.lilei.test.threadlocaltest;/** * 序列号生成器 * Created by Administrator on 2017/10/22. */public interface Sequence {    int getNumbers();}
  • 2.定义一个线程类
package com.lilei.test.threadlocaltest;/** * Created by Administrator on 2017/10/22. */public class ClientThread extends Thread {    private Sequence sequence;    public ClientThread(Sequence sequence) {        this.sequence = sequence;    }    @Override    public void run() {        for (int i = 0; i < 3; i++){            System.out.println(Thread.currentThread().getName()+" =>"+sequence.getNumbers());        }    }}
  • 3.定义一个接口实现类
package com.lilei.test.threadlocaltest;/** * Created by Administrator on 2017/10/22. */public class SequenceA implements Sequence {    private static int number = 0;    public int getNumbers() {        number = number + 1;        return number;    }    public static void main(String[] args) {        Sequence sequence = new SequenceA();        ClientThread thread1 = new ClientThread(sequence);        ClientThread thread2 = new ClientThread(sequence);        ClientThread thread3 = new ClientThread(sequence);        thread1.start();        thread2.start();        thread3.start();    }}
  • 4.程序运行结果为

Thread-0 =>1
Thread-0 =>2
Thread-0 =>3
Thread-1 =>4
Thread-1 =>5
Thread-1 =>6
Thread-2 =>7
Thread-2 =>8
Thread-2 =>9

  • 5.结果分析

a.三个线程并不是同时输出了0 1 2 的输出顺序,因为线程是随机的可以理解
b.三个线程并没有按照我们想要的结果输入,而是共享了一个变量,说明线程不安全

4.问题解决

a.如何才能做到线程安全,也就是说不线程拥有自己的static变量呢,就是使用ThreadLocal这个对象

package com.lilei.test.threadlocaltest;/** * Created by Administrator on 2017/10/22. */public class SequenceB implements Sequence {    private static ThreadLocal<Integer> numberContainer = new ThreadLocal<Integer>(){        @Override        protected Integer initialValue() {            return 0;        }    };    public int getNumbers() {        numberContainer.set(numberContainer.get() + 1);        return numberContainer.get();    }    public static void main(String[] args) {        Sequence sequence = new SequenceB();        ClientThread thread1 = new ClientThread(sequence);        ClientThread thread2 = new ClientThread(sequence);        ClientThread thread3 = new ClientThread(sequence);        thread1.start();        thread2.start();        thread3.start();    }}
  • b.程序运行结果:

Thread-2 =>1
Thread-0 =>1
Thread-2 =>2
Thread-0 =>2
Thread-2 =>3
Thread-0 =>3
Thread-1 =>1
Thread-1 =>2
Thread-1 =>3

  • c.ThreadLocal的常用api

i public void set(T value) 将值放入到线程局部变量中
ii pubic void get() 从线程的局部变量中获取值
iii public void remove() 从线程局部变量移除值
iv protected T initialValue() 返回线程局部变量的初始值,默认为nulla

原创粉丝点击