多线程高级面试题

发布时间:2024年01月07日

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(锁),所以让当前线程等待某个对象的锁,当然应该通过这个对象来操作,而不是用当前线程来操作,因为当前线程可能会等待多个线程的锁,如果通过线程来操作,就非常复杂了。

文章来源:https://blog.csdn.net/qq_57747969/article/details/135384432
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。