java并发(2)ThreadLocal的使用及实现原理(使用)
2017-08-02 16:33
543 查看
ThreadLocal:线程本地变量.
在java的java.lang.Thread类中有个threadLocals变量,该变量的类型是ThreadLocal的内部类ThreadLocalMap,该变量是一个map,保存着该线程的独有的变量副本,所有通过ThreadLocal维护的变量都是存放在当前线程的这个threadLocals的Map中所以这些变量都是线程安全的,下面是Thread类中的该变量定义:
简单来说ThreadLocal作为解决并发问题的另一种思路是:用“以空间换取时间”的方式来代替“以时间换取空间”的sychronized方式。每一个线程都有自己独有的ThreadLocalMap变量表,也就不存在线程安全问题了,值得注意的是,不要错误的理解为ThreadLocal是用来解决共享变量和协调线程同步的方案,它是为了方便每个线程处理自己的状态而引入的一个机制。
下面看看java中ThreadLocal怎么使用:
ThreadLocal<T>是java.lang包中的一个类,该类有5个方法如下:
下面通过一个列子来说明ThreadLocal怎么使用:
先创建一个任务:
该任务实现每个线程计数,通过ThreadLocal的方式管理计数器,通过覆盖initialValue方法的方式,给该计数器赋初始值为1,然后在add的时候先从本地变量中拿出计数器的值,然后再加1,然后再set回去,add方法有三个步骤,即:取值,+1,写入,但是可以看到我们没有对该方法加任何的锁操作,但是它依然是线程安全的,因为每个线程都会有一份独立的本地变量,也就是每个线程都有一个计数器,它们互相不影响。接下来创建一个可运行任务,实现Runnable接口:
该对象持有一个Task对象,然后让task调
a64d
用add方法十次并打印,创建该类的目的是为了让所有的ThreadLocalTask对象都持有同一个Task对象,以验证不同的线程对于该Task对象有不同本地线程变量。接下来创建一个测试类:
通过创建一个线程池让五个ThreadLocalTask任务同时运行,结果:
pool-1-thread-1--1
pool-1-thread-1--2
pool-1-thread-1--3
pool-1-thread-2--1
pool-1-thread-3--1
pool-1-thread-3--2
pool-1-thread-3--3
pool-1-thread-3--4
pool-1-thread-2--2
pool-1-thread-2--3
pool-1-thread-2--4
pool-1-thread-2--5
pool-1-thread-2--6
pool-1-thread-2--7
pool-1-thread-2--8
pool-1-thread-2--9
pool-1-thread-2--10
pool-1-thread-1--4
pool-1-thread-1--5
pool-1-thread-1--6
pool-1-thread-4--1
pool-1-thread-4--2
pool-1-thread-4--3
pool-1-thread-1--7
pool-1-thread-5--1
pool-1-thread-5--2
pool-1-thread-5--3
pool-1-thread-3--5
pool-1-thread-5--4
pool-1-thread-1--8
pool-1-thread-1--9
pool-1-thread-4--4
pool-1-thread-1--10
pool-1-thread-5--5
pool-1-thread-3--6
pool-1-thread-5--6
pool-1-thread-4--5
pool-1-thread-5--7
pool-1-thread-3--7
pool-1-thread-5--8
pool-1-thread-4--6
pool-1-thread-4--7
pool-1-thread-5--9
pool-1-thread-3--8
pool-1-thread-5--10
pool-1-thread-4--8
pool-1-thread-3--9
pool-1-thread-4--9
pool-1-thread-3--10
pool-1-thread-4--10
从结果可以看出每个线程都是从1开始到10结束,均互不干扰的执行了10次加运算。
以上就是ThreadLocal的简单使用,接下来分析一下在jdk8中ThreadLocal的实现原理:java并发(3)ThreadLocal的使用及实现原理(实现原理)
在java的java.lang.Thread类中有个threadLocals变量,该变量的类型是ThreadLocal的内部类ThreadLocalMap,该变量是一个map,保存着该线程的独有的变量副本,所有通过ThreadLocal维护的变量都是存放在当前线程的这个threadLocals的Map中所以这些变量都是线程安全的,下面是Thread类中的该变量定义:
/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null;
简单来说ThreadLocal作为解决并发问题的另一种思路是:用“以空间换取时间”的方式来代替“以时间换取空间”的sychronized方式。每一个线程都有自己独有的ThreadLocalMap变量表,也就不存在线程安全问题了,值得注意的是,不要错误的理解为ThreadLocal是用来解决共享变量和协调线程同步的方案,它是为了方便每个线程处理自己的状态而引入的一个机制。
下面看看java中ThreadLocal怎么使用:
ThreadLocal<T>是java.lang包中的一个类,该类有5个方法如下:
T | get() Returns the value in the current thread's copy of this thread-local variable. 该方法返回一个当前线程所对应的ThreadLocal维护的变量 |
protected T | initialValue() Returns the current thread's "initial value" for this thread-local variable. 该方法在线程第一次调用get方法的时候会被执行,返回一个当前ThreadLocal维护的变量 的初始值,该方法被声明为protected,目的是为了让这类去覆盖它从而设置线程变量的 初始值,如果不覆盖,默认返回null。 |
void | remove() Removes the current thread's value for this thread-local variable. 删除当前线程的本地变量,目的是为了减少内存占用,但是当线程销毁时该本地变量也会 被回收,所以该方法不是必须的 |
void | set(T value) Sets the current thread's copy of this thread-local variable to the specified value. 为当前线程的当前ThreadLocal维护的变量设置值 |
static <S> ThreadLocal<S> | withInitial(Supplier<? extends S> supplier) Creates a thread local variable. 创建一个ThreadLocal并返回。 |
先创建一个任务:
public class Task { ThreadLocal<Integer> value = new ThreadLocal<Integer>(){ @Override protected Integer initialValue() { return 1; } }; public Integer add(){ value.set(value.get()+1); return value.get(); } @Override public String toString() { return value.get().toString(); } }
该任务实现每个线程计数,通过ThreadLocal的方式管理计数器,通过覆盖initialValue方法的方式,给该计数器赋初始值为1,然后在add的时候先从本地变量中拿出计数器的值,然后再加1,然后再set回去,add方法有三个步骤,即:取值,+1,写入,但是可以看到我们没有对该方法加任何的锁操作,但是它依然是线程安全的,因为每个线程都会有一份独立的本地变量,也就是每个线程都有一个计数器,它们互相不影响。接下来创建一个可运行任务,实现Runnable接口:
public class ThreadLocalTask implements Runnable { private Task task; public ThreadLocalTask(Task task) { this.task = task; } @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+"--"+task.add()); } } }
该对象持有一个Task对象,然后让task调
a64d
用add方法十次并打印,创建该类的目的是为了让所有的ThreadLocalTask对象都持有同一个Task对象,以验证不同的线程对于该Task对象有不同本地线程变量。接下来创建一个测试类:
public class ThreadLocalTest { public static void main(String[] args){ Task task = new Task(); ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { ThreadLocalTask threadLocalTask = new ThreadLocalTask(task); exec.execute(threadLocalTask); } exec.shutdown(); } }
通过创建一个线程池让五个ThreadLocalTask任务同时运行,结果:
pool-1-thread-1--1
pool-1-thread-1--2
pool-1-thread-1--3
pool-1-thread-2--1
pool-1-thread-3--1
pool-1-thread-3--2
pool-1-thread-3--3
pool-1-thread-3--4
pool-1-thread-2--2
pool-1-thread-2--3
pool-1-thread-2--4
pool-1-thread-2--5
pool-1-thread-2--6
pool-1-thread-2--7
pool-1-thread-2--8
pool-1-thread-2--9
pool-1-thread-2--10
pool-1-thread-1--4
pool-1-thread-1--5
pool-1-thread-1--6
pool-1-thread-4--1
pool-1-thread-4--2
pool-1-thread-4--3
pool-1-thread-1--7
pool-1-thread-5--1
pool-1-thread-5--2
pool-1-thread-5--3
pool-1-thread-3--5
pool-1-thread-5--4
pool-1-thread-1--8
pool-1-thread-1--9
pool-1-thread-4--4
pool-1-thread-1--10
pool-1-thread-5--5
pool-1-thread-3--6
pool-1-thread-5--6
pool-1-thread-4--5
pool-1-thread-5--7
pool-1-thread-3--7
pool-1-thread-5--8
pool-1-thread-4--6
pool-1-thread-4--7
pool-1-thread-5--9
pool-1-thread-3--8
pool-1-thread-5--10
pool-1-thread-4--8
pool-1-thread-3--9
pool-1-thread-4--9
pool-1-thread-3--10
pool-1-thread-4--10
从结果可以看出每个线程都是从1开始到10结束,均互不干扰的执行了10次加运算。
以上就是ThreadLocal的简单使用,接下来分析一下在jdk8中ThreadLocal的实现原理:java并发(3)ThreadLocal的使用及实现原理(实现原理)
相关文章推荐
- java并发(3)ThreadLocal的使用及实现原理(实现原理)
- java并发编程学习: ThreadLocal使用及原理
- Java高并发编程三--volatile使用及其实现原理
- java并发编程学习: 阻塞队列 使用 及 实现原理
- Java并发学习之ThreadLocal使用及原理介绍
- ThreadLocal的实现原理,及使用实例,解决spring,hibernate非web项目下的懒加载 no session or session was closed(2)!
- java中使用线程实现Timer(定时器)原理和源码
- java中使用线程实现Timer(定时器)原理和源码
- java中使用线程实现Timer(定时器)原理和源码
- java中使用公钥加密私钥解密原理实现license控制
- Java并发包中的同步队列SynchronousQueue实现原理
- java中使用公钥加密私钥解密原理实现license控制
- java中使用公钥加密私钥解密原理实现license控制
- Android学习笔记---java实现多线程下载器,30_多线程下载原理介绍和使用
- Java枚举(用Java普通类模拟枚举的实现原理及JDK枚举API使用示例)
- java中使用线程实现Timer(定时器)原理和源码
- java中使用线程实现Timer(定时器)原理和源码
- java中使用线程实现Timer(定时器)原理和源码
- Java枚举(用Java普通类模拟枚举的实现原理及JDK枚举API使用示例)
- java中使用线程实现Timer(定时器)原理和源码