并发与多线程
main方法里没有创建新的线程,执行main方法一共需要几个线程?
可以使用ManagementFactory
的getThreadMXBean
方法获取ThreadMXBean
信息,进而获取线程信息进行查看。代码:
package Exercise;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
public class Test {
public static void main(String[] args) {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
for (ThreadInfo threadInfo : threadInfos) {
System.out.println(threadInfo.getThreadId() ":" threadInfo.getThreadName());
}
}
}
运行结果:
代码语言:javascript复制6:Monitor Ctrl-Break
5:Attach Listener
4:Signal Dispatcher
3:Finalizer
2:Reference Handler
1:main
答案是6个,通过每个线程的名字可以知道他们的作用。
ThreadLocal
ThreadLocal
为每个线程创建一个变量的副本,对彼此不可见,它基于ThreadLocalMap
实现。
核心机制如下:
- 每个Thread线程内部都有一个
map
(ThreadLocalMap)。 - map里面存储线程本地对象
key
和线程变量副本value
。 - Thread内部的
map
是由ThreadLocal
维护的,由ThreadLocal
负责向map
获取和设置线程的变量值。
每个线程只能获取自己的副本值,不能获取其他线程的,这样就形成了隔离,互不干扰。
ThreadLocal类提供了以下几个核心方法:
1.get()
方法:获取当前线程的副本变量值。
2.set()
方法:设置当前线程的副本变量值。
3.remove()
方法:移除当前线程的副本变量值。
4.initilaValue()
方法:初始化当前线程的副本变量值,初始化为null
。
ThreadLocalMap
是ThreadLocal
内部的一个map实现,
它和HashMap
实现自Map
接口不一样,它没有实现任何接口,仅供ThreadLocal
内部使用,数据结构采用数组加开放地址法,Entry
继承自WeakReference
,是基于ThreadLocal
场景下实现的特殊Map,源码见参考文献第一篇。
ThreadLocal的应用场景:
- 在对象进行跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。
- 线程间数据隔离。
- 进行事务操作,用于存储事务信息。
- ·数据库连接,Session会话管理。
发生了死锁,如何排查
使用jps
获取发生死锁的进程号。
使用jstack
进程号查看该进程堆栈,它会详细显示死锁数量,相关联的线程,发生死锁的大致代码位置等信息。
jconsole
也可以查看相关信息。
黑名单功能如何实现
使用写时复制容器CopyOnWriteArrayList
实现。
什么是写时复制容器
写时复制是指,在并发访问的场景下,需要修改Java中容器中的元素时,不直接修改该容器中,而是先复制一份副本,在副本上进行修改。修改完成之后,将指向原来容器的引用指向新的副本容器。
写时复制带来的影响
- 由于不会修改原始容器,只修改副本容器,可以对原始容器进行并发地读。其次,实现了读操作和写操作的分离:读操作发生在原始容器上,写操作发生在副本容器上。
- 数据一致性问题:读操作的线程可能不会立即读取到新修改的数据,因为修改操作可能会发生在副本上,但最终修改操作会完成并更新容器,因此只能保证最终一致性。
写时复制容器
JDK中提供了CopyOnWriteArrayList
和CopyOnWriteArraySet
类,但是没有提供CopyOnWriteHashMap,可以自己实现一个。
写时复制容器适用的场景
CopyOnWrite容器适用于读多写少的场景。因为写操作时,需要复制一个容器,造成内存开销很大,也需要根据实际应用把握初始容器的大小。
不适合数据的强一致性场合。若要求数据修改之后能立即被读到,则不能使用写时复制技术,因为它只能保证最终一致性。
参考文献
深入源码理解ThreadLocal和ThreadLocalMap
面试官:知道ThreadLocal嘛?谈谈你对它的理解?(基于jdk1.8)
JAVA中写时复制(Copy-On-Write)Map实现