1. 什么是 ThreadLocal?
参考答案
ThreadLocal 叫做本地线程变量,意思是说,ThreadLocal 中填充的的是当前线程的变量,该变量对其他线程而言是封闭且隔离的,ThreadLocal 为变量在每个线程中创建了一个副本,这样每个线程都可以访问自己内部的副本变量。
2. ThreadLocal 有哪些应用场景?
参考答案
在进行对象跨层传递的时候,使用 ThreadLocal 可以避免多次传递,打破层次间的约束。线程间数据隔离进行事务操作,用于存储线程事务信息。数据库连接,Session 会话管理。
3. ThreadLocal 是否会内存泄漏?
参考答案
会。当仅仅只有 ThreadLocalMap 中的 Entry 的 key 指向 ThreadLocal 的时候,ThreadLocal 会进行回收的!!!ThreadLocal 被垃圾回收后,在 ThreadLocalMap 里对应的 Entry 的键值会变成 null,但是 Entry 是强引用,那么 Entry 里面存储的 Object,并没有办法进行回收,所以有内存泄漏的风险。
4. 为什么要使用线程池?
参考答案
降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度,当任务到达时,任务可以不需要等到线程创建就立即执行。提高线程的可管理性,线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以统一分配。
5. execute() 和 submit() 区别?
参考答案
execute()方法只能执行 Runnable 类型的任务。submit () 方法可以执行 Runnable 和 ca11ab1e 类型的任务。submit()方法可以返回持有计算结果的 Future 对象,同时还可以抛出异常,而 execute() 方法不可以。
6. shutdown() 和 shutdownNow() 区别?
参考答案
shutdown() 会将线程池状态置为 SHUTDOWN,不再接受新的任务,同时会等待线程池中已有的任务执行完成再结束。shutdownNow() 会将线程池状态置为 SHUTDOWN,对所有线程执行 interrupt() 操作,清空队列,并将队列中的任务返回回来。
7. volatile 的作用和特性?
参考答案
作用:volatile 是一个轻量级的 synchronized,一般作用于变量,在多处理器开发的过程中保证了内存的可见性。相比于 synchronized 关键字,volatile 关键字的执行成本更低,效率更高。特性:可见性:volatile 可以保证不同线程对共享变量进行操作时的可见性。即当一个线程修改了共享变量时,另一个线程可以读取到共享变量被修改后的值。有序性:volatile 会通过禁止指令重排序进而保证有序性。
8. volatile 和 synchronized 区别?
参考答案
volatile 是在告诉 jvm 当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取,synchronized 则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。volatile 仅能使用在变量级别;synchronized 则可以使用在变量、方法、和类级别的volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则可以保证变量的修改可见性和原子性volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。volatile 标记的变量不会被编译器优化;synchronized 标记的变量可以被编译器优化
9. 什么是乐观锁?什么是悲观锁?
参考答案
悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。悲观锁适合写操作多的场景,先加锁可以保证写操作时数据正确。乐观锁适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。
10. 什么是可重入锁?什么是非可重入锁?
参考答案
可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者 class),不会因为之前已经获取过还没释放而阻塞。非可重入锁,则与上面相反,再进入该线程的内层方法不会自动获取锁进而造成线程出现死锁,整个等待队列中的所有线程都无法被唤醒。
11. 为什么 wait,notify 和 notifyAll 这些方法不在 Thread 类里面??
参考答案
原因是每个对象都拥有 monitor(锁),所以让当前线程等待某个对象的锁,当然应该通过这个对象来操作,而不是用当前线程来操作,因为当前线程可能会等待多个线程的锁,如果通过线程来操作,就非常复杂了。