根据众多面试的同学反馈的面试题,给大家整理一版最新的面试专题,希望对大家有所帮助。
先来看看经常会问到的问题。
看看你能回答几个哦。
然后我们再来看看每个问题我们应该怎么来回答吧!
线程池的原理,为什么要创建线程池?创建线程池的方式有哪些?
原理和创建线程池的实现请我之前整理的这篇文章:
创建线程池的几种方式:
线程的生命周期,什么时候会出现僵死进程;
僵死进程是指子进程退出时,父进程并未对其发出的SIGCHLD信号进行适当处理,导致子 进程停留在僵死状态等待其父进程为其收尸,这个状态下的子进程就是僵死进程。
说说线程安全问题,什么是线程安全,如何实现线程安全;
实现线程安全的三种方式
1)互斥同步
2)非阻塞同步
3)无同步方案
多线程的安全机制:数据安全机制
创建线程池有哪几个核心参数? 如何合理配置线程池的大小?
首先我们来看下核心参数:
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数量大小
int maximumPoolSize, // 线程池最大容纳线程数
long keepAliveTime, // 线程空闲后的存活时长
TimeUnit unit,
//缓存异步任务的队列 //用来构造线程池里的worker线程
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
//线程池任务满载后采取的任务拒绝策略
RejectedExecutionHandler handler)
相关参数介绍:
具体可以参考本文的详解:线程池核心配置讲解
然后我们需要来看先线程池的大小分配了。
线程池究竟设置多大要看你的线程池执行的什么任务了,CPU密集型、IO密集型、混合型,任 务类型不同,设置的方式也不一样。
任务一般分为:CPU密集型、IO密集型、混合型,对于不同类型的任务需要分配不同大小的线程池。
3.1 CPU密集型
尽量使用较小的线程池,一般Cpu核心数+1
3.2 IO密集型
最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目
3.3 混合型
可以将任务分为CPU密集型和IO密集型,然后分别使用不同的线程池去处理,按情况而定
问题:volatile、ThreadLocal的使用场景和原理?
volatile变量进行写操作时,JVM 会向处理器发送一条 Lock 前缀的指令,将这个变量所在缓 存行的数据写会到系统内存。
Lock 前缀指令实际上相当于一个内存屏障(也成内存栅栏),它确保指令重排序时不会把其 后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内 存屏障这句指令时,在它前面的操作已经全部完成。
volatile的适用场景:
ThreadLocal是用来维护本线程的变量的,并不能解决共享变量的并发问题。ThreadLocal是 各线程将值存入该线程的map中,以ThreadLocal自身作为key,需要用时获得的是该线程之前 存入的值。如果存入的是共享变量,那取出的也是共享变量,并发问题还是存在的。
ThreadLocal的适用场景
场景:数据库连接、Session管理
问题:ThreadLocal什么时候会出现OOM的情况?为什么?
ThreadLocal变量是维护在Thread内部的,这样的话只要我们的线程不退出,对象的引用就会 一直存在。当线程退出时,Thread类会进行一些清理工作,其中就包含ThreadLocalMap, Thread调用exit方法如下:
&esmp; ThreadLocal在没有线程池使用的情况下,正常情况下不会存在内存泄露,但是如果使用了线程 池的话,就依赖于线程池的实现,如果线程池不销毁线程的话,那么就会存在内存泄露。
问题:synchronized、volatile有什么区别