Java 面试知识点解析(二)——高并发编程篇 (5)

一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和 long 都是64位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但 Java 中 volatile 型的 long 或 double 变量的读写是原子的。

volatile 修复符的另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(write barrier),读一个 volatile 变量之前,会插入一个读屏障(read barrier)。意思就是说,在你写一个 volatile 域时,能保证任何线程都能看到你写的值,同时,在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。

5)ThreadLocal(线程局部变量)关键字:

答:当使用 ThreadLocal 维护变量时,其为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立的改变自己的副本,而不会影响其他线程对应的副本。

ThreadLocal 内部实现机制:

每个线程内部都会维护一个类似 HashMap 的对象,称为 ThreadLocalMap,里边会包含若干了 Entry(K-V 键值对),相应的线程被称为这些 Entry 的属主线程;

Entry 的 Key 是一个 ThreadLocal 实例,Value 是一个线程特有对象。Entry 的作用即是:为其属主线程建立起一个 ThreadLocal 实例与一个线程特有对象之间的对应关系;

Entry 对 Key 的引用是弱引用;Entry 对 Value 的引用是强引用。

Java 面试知识点解析(二)——高并发编程篇

6)线程池有了解吗?(必考)

答:java.util.concurrent.ThreadPoolExecutor 类就是一个线程池。客户端调用 ThreadPoolExecutor.submit(Runnable task) 提交任务,线程池内部维护的工作者线程的数量就是该线程池的线程池大小,有 3 种形态:

当前线程池大小 :表示线程池中实际工作者线程的数量;

最大线程池大小 (maxinumPoolSize):表示线程池中允许存在的工作者线程的数量上限;

核心线程大小 (corePoolSize ):表示一个不大于最大线程池大小的工作者线程数量上限。

如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队;

如果运行的线程等于或者多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不是添加新线程;

如果无法将请求加入队列,即队列已经满了,则创建新的线程,除非创建此线程超出 maxinumPoolSize, 在这种情况下,任务将被拒绝。

面试官:我们为什么要使用线程池?

答:

减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

可以根据系统的承受能力,调整线程池中工作线程的数目,放置因为消耗过多的内存,而把服务器累趴下(每个线程大约需要 1 MB 内存,线程开的越多,消耗的内存也就越大,最后死机)

面试官:核心线程池内部实现了解吗?

答:对于核心的几个线程池,无论是 newFixedThreadPool() 方法,newSingleThreadExecutor() 还是 newCachedThreadPool() 方法,虽然看起来创建的线程有着完全不同的功能特点,但其实内部实现均使用了 ThreadPoolExecutor 实现,其实都只是 ThreadPoolExecutor 类的封装。

为何 ThreadPoolExecutor 有如此强大的功能呢?我们可以来看一下 ThreadPoolExecutor 最重要的构造函数:

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

函数的参数含义如下:

corePoolSize:指定了线程池中的线程数量

maximumPoolSize:指定了线程池中的最大线程数量

keepAliveTime:当线程池线程数量超过 corePoolSize 时,多余的空闲线程的存活时间。即,超过了 corePoolSize 的空闲线程,在多长时间内,会被销毁。

unit: keepAliveTime 的单位。

workQueue:任务队列,被提交但尚未被执行的任务。

threadFactory:线程工厂,用于创建线程,一般用默认的即可。

handler:拒绝策略。当任务太多来不及处理,如何拒绝任务。

7)Atomic关键字:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzdwjz.html