思维导图
一、常见知识点
1.线程与进程的区别:
2.多线程中的上下文切换:
4.原子操作,JUC中原子操作类有哪些:
5.CAS操作及缺点:
关于ABA问题,详见以下链接:
CAS中的ABA问题
6.java中的volatile变量作用:
7.volatile和atomic变量区别:
8.lock接口与synchronized区别:
9.乐观锁和悲观锁的理解及实现:
10.死锁:
11.callable及future:
12.futureTask的底层原理:
13.阻塞队列及实现原理:
这两个附加的操作是:
- 在队列为空时,获取元素的线程会等待队列变为非空。
- 当队列满时,存储元素的线程会等待队列可用。
常用于生产消费者模型
14.不可变对象对并发应用的帮助
15.生产消费者模型作用:
16.copyOnWriteArrayList应用场景:
17.java单例:
18.双重检查锁定DCL的单例:
19.AQS:
20.wait、notify、notifyAll为什么不在thread类中:
类似问题:为什么 sleep() 方法不定义在object中?
- sleep()是Thread静态类,属于线程级别的。
- 是一个线程的运行状态控制,为了让线程在限定的时间后去执行。
详细如下链接:
关于为什么线程通信的方法wait()、notify()、notifyAll()被定义在Object类里面?而sleep为什么定义在Thread类里面?
为什么wait方法在object类中,sleep方法在Thread类中?
21 ThreadLocal
21.1 作用
(1)通常情况下,我们创建的变量是可以被任何⼀个线程访问并修改的。
如果想实现每一个线程都有自己的专属本地变量该如何解决呢?
(2)ThreadLocal 类主要解决的就是让每个线程绑定自己的值。可以将 ThreadLocal 类形象的⽐喻成存放数据的盒⼦,盒⼦中可以存储每个线程的私有数据
(3)如果你创建了⼀个 ThreadLocal 变量,那么访问这个变量的每个线程都会有这个变量的本地副本。
他们可以使⽤ get() 和 set() ⽅法来获取默认值或将其值更改为当前线程所存的副本的值,从⽽避免了线程安全问题。
21.2 应用场景
(1)进行对象跨层传递时,可以使用ThreadLocal可以避免多次传递,打破层次间的约束
(2)线程间数据隔离
(3)进行事务操作,用于存储线程事务信息
(4)数据库连接、session会话管理
21.3 原理
21.3.1 数据结构如下图:
21.3.2 ThreadLocal类的set()方法
public void set(T value) {
//获取当前请求的线程
Thread t = Thread.currentThread();
//取出 Thread 类内部的 threadLocals 变量(哈希表结构)
ThreadLocalMap map = getMap(t);
if (map != null)
// 将需要存储的值放入到这个哈希表中
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
(1)最终的变量是放在了当前线程的 ThreadLocalMap 中,并不是存在 ThreadLocal 上,ThreadLocal 可以理解为只是ThreadLocalMap的封装,传递了变量值。
(2)ThrealLocal 类中可以通过Thread.currentThread()获取到当前线程对象后,直接通过getMap(Thread t)可以访问到该线程的ThreadLocalMap对象。
(3)每个Thread中都具备一个ThreadLocalMap,而ThreadLocalMap可以存储以ThreadLocal为 key ,Object 对象为 value 的键值对。
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
//......
}
(4)ThreadLocalMap是ThreadLocal的静态内部类。
21.4 ThreadLocal 内存泄露
21.4.1 强弱引用
(1)强引用:new对象,不会被垃圾回收器回收,即使抛出outofmemoryerror使程序停止
如何回收强引用:显式将引用赋值为null,jvm就会在合适的时候回收
(2)弱引用:jvm进行垃圾回收时候,无论内存是否充足,都会回收别弱引用关联的对象,一般在缓存中使用。
21.4.2 问题是怎么导致的?
(1)ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,而 value 是强引用。所以,如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候,key 会被清理掉,而 value 不会被清理掉。
(2)ThreadLocalMap 中就会出现 key 为 null 的 Entry。假如我们不做任何措施的话,value 永远无法被 GC 回收,这个时候就可能会产生内存泄露。
(3)hreadLocalMap 实现中已经考虑了这种情况,在调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
21.4.3 如何解决?
(1)使用完 ThreadLocal方法后 最好手动调用remove()方法
(2)将ThreadLocal变量定义为private static
本篇文章主要参考链接如下:
持续更新中…
随心所往,看见未来。Follow your heart,see light!
欢迎点赞、关注、留言,一起学习、交流!