Java多线程之ThreadLocal
来源:互联网 发布:重启后正在准备windows 编辑:程序博客网 时间:2024/05/17 07:47
ThreadLocal直译为"本地线程",但它并不是这样。ThreadLocal本身其实是一个容器,用于 存放线程的局部变量,这个类能使线程中的某个值与保存值的线程对象关联起来。ThreadLocal提供了get和set等访问接口或方法,这些方法为每个使用该变量的线程都存有一份副本,因此get总是返回当前执行线程在调用set时设置的最新值。下面将以实例代码说明。场景:一个序列号生成器的程序同时会有多个线程访问它,要保证每个线程得到的序列号都是自增的,而相互不干扰。先定义一个接口:
public interface Sequence { int getNumber();}
每次调用getNumber()方法可获取序列号,下次在调用时,序列号会自增。
线程类
public class ClientThread implements Runnable { 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.getNumber()); } }}
错误的案例
public class SequenceA implements Sequence { private static int number = 0; @Override public int getNumber() { number++; return number; } public static void main(String[] args) { Sequence sequence = new SequenceA(); ClientThread clientThread = new ClientThread(sequence); ClientThread clientThread1 = new ClientThread(sequence); ClientThread clientThread2 = new ClientThread(sequence); new Thread(clientThread).start(); new Thread(clientThread1).start(); new Thread(clientThread2).start(); }}
运行结果:Thread-0 => 1Thread-0 => 2Thread-0 => 3Thread-1 => 4Thread-1 => 5Thread-1 => 6Thread-2 => 7Thread-2 => 8Thread-2 => 9因为number是static修饰,属于共享资源,所以number一直自增,不能保证线程安全。
使用ThreadLocal
public class SequenceB implements Sequence { private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){ @Override protected Integer initialValue() { return 0; } }; @Override public int getNumber() { threadLocal.set(threadLocal.get() + 1); return threadLocal.get(); } public static void main(String[] args) { Sequence sequence = new SequenceB(); ClientThread clientThread = new ClientThread(sequence); ClientThread clientThread1 = new ClientThread(sequence); ClientThread clientThread2 = new ClientThread(sequence); new Thread(clientThread).start(); new Thread(clientThread1).start(); new Thread(clientThread2).start(); }}
运行结果Thread-0 => 1Thread-1 => 1Thread-1 => 2Thread-1 => 3Thread-2 => 1Thread-2 => 2Thread-2 => 3Thread-0 => 2Thread-0 => 3从运行结果可以看出,每个线程相互独立了,同样是static变量,对于不同的线程而言,它没有被共享,而是每个线程各一份,这样就保证了线程安全。也就是说,ThreadLocal为每个线程提供了独立的副本。ThreadLocal的APIpublic void set(T value):将值放入线程局部变量中;public T get():从线程局部变量中获取值;public void remove():从线程局部变量中移除值;protected T initialValue():返回线程局部变量中的初始值(默认为null)
自己实现ThreadLocal
ThreadLocal其实就是封装了一个线程安全的Map
public class MyThreadLocal<T> { //封装一个线程安全的Map,以线程对象为key,线程变量T为value private Map<Thread, T> threadTMap = Collections.synchronizedMap(new HashMap<Thread, T>()); public void set(T t) { threadTMap.put(Thread.currentThread(), t); } public T get() { Thread thread = Thread.currentThread(); T value = threadTMap.get(thread); if (value == null && !threadTMap.containsKey(thread)) { value = initValue(); threadTMap.put(thread, value); } return value; } public void remove() { threadTMap.remove(Thread.currentThread()); } protected T initValue() { return null; }}
使用MyThreadLocal来实现:
public class SequenceC implements Sequence { private static MyThreadLocal<Integer> myThreadLocal = new MyThreadLocal<Integer>(){ @Override protected Integer initValue() { return 0; } }; @Override public int getNumber() { myThreadLocal.set(myThreadLocal.get() + 1); return myThreadLocal.get(); } public static void main(String[] args) { Sequence sequenceC = new SequenceC(); new Thread(new ClientThread(sequenceC)).start(); new Thread(new ClientThread(sequenceC)).start(); new Thread(new ClientThread(sequenceC)).start(); }}
运行结果:Thread-0 => 1Thread-0 => 2Thread-0 => 3Thread-1 => 1Thread-1 => 2Thread-1 => 3Thread-2 => 1Thread-2 => 2Thread-2 => 3运行效果和之前一样,同样正确。ThreadLocal对象通常用于防止对可变的单实例变量或全局变量进行共享。例如:在单线程应用程序中可能维持一个全局的数据库连接,并在程序启动时初始化这个连接,从而避免在调用每个方法时都要传递一个Connection对象。由于JDBC的连接对象不一定是线程安全的,因此,当多线程应用程序在没有协同的情况下使用全局变量时,就不是线程安全的。通过将JDBC的连接保存到ThreadLocal对象中,每个线程都会有属于自己的来连接。
阅读全文
0 0
- Java多线程之ThreadLocal
- Java多线程之ThreadLocal
- JAVA多线程之ThreadLocal
- Java多线程之 ThreadLocal
- java多线程之ThreadLocal
- Java多线程之----ThreadLocal
- Java多线程之ThreadLocal
- Java多线程之ThreadLocal
- java多线程之ThreadLocal
- java多线程之ThreadLocal
- Java 多线程之--ThreadLocal 简介
- (四)java多线程之ThreadLocal
- java多线程并发控制之ThreadLocal
- java多线程之——ThreadLocal
- (8)Java多线程之ThreadLocal
- java多线程并发控制之ThreadLocal
- Java多线程学习之ThreadLocal源码分析
- java多线程之ThreadLocal源码分析
- 关于运算符重载的问题
- 先验和后验概率
- 【操作系统】-5大功能
- 017年Android百大框架排行榜
- c# 获取毫秒值,时间戳
- Java多线程之ThreadLocal
- leetcode 22. Generate Parentheses
- linux的简单命令(持续记录)
- mysql之存储过程,函数,游标
- 47 使用linux内核源码里的按键驱动<GPIO Buttons>
- Online Sequence-to-Sequence Active Learning for Open-Domain Dialogue Generation
- BZOJ 4435: [Cerc2015]Juice Junctions tarjan
- Vue2.0 推荐开发环境
- 关于fragment懒加载问题