ConcurrentHashMap 的存储结构是怎样的?
Java7 中 ConcurrnetHashMap 使用的分段锁,也就是每一个 Segment 上同时只有一
个线程可以操作,每一个 Segment 都是一个类似 HashMap 数组的结构,它可以扩容,
它的冲突会转化为链表。但是 Segment 的个数一但初始化就不能改变,默认 Segment
的个数是 16 个。
Java8 中的 ConcurrnetHashMap 使用的 Synchronized 锁加 CAS 的机制。结构也由
Java7 中的 Segment 数组 + HashEntry 数组 + 链表 进化成了 Node 数组 + 链表 / 红
黑树,Node 是类似于一个 HashEntry 的结构。它的冲突再达到一定大小时会转化成红
黑树,在冲突小于一定数量时又退回链表。
线程池大小如何设置?
CPU 密集型任务(N+1): 这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N
(CPU 核心数)+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,
或者其它原因导致的任务暂停而带来的影响。一旦任务暂停,CPU 就会处于空闲状态,
而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间。
I/O 密集型任务(2N): 这种任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线
程在处理 I/O 的时间段内不会占用 CPU 来处理,这时就可以将 CPU 交出给其它线程使
用。因此在 I/O 密集型任务的应用中,我们可以多配置一些线程,具体的计算方法是 2N。
如何判断是 CPU 密集任务还是 IO 密集任务?
CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内存中对大量数据进行排序。
单凡涉及到网络读取,文件读取这类都是 IO 密集型,这类任务的特点是 CPU 计算耗费时间
相比于等待 IO 操作完成的时间来说很少,大部分时间都花在了等待 IO 操作完成上。
IO 密集=Ncpu*2 是怎么计算出来?
I/O 密集型任务任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线程在处理I/O 的时间段内不会占用 CPU 来处理,这时就可以将 CPU 交出给其它线程使用。
因此在I/O 密集型任务的应用中,我们可以多配置一些线程。例如:数据库交互,文件上传下载,网络传输等。
IO 密集型,即该任务需要大量的 IO,即大量的阻塞,故需要多配置线程数。
学习之路贵在坚持,关注我!
浩说编程陪你每天三道高频面试题,日积月累一定会有所收获!