多线程面试题
线程安全体现在哪些方面?
原子性:同一时刻只能有一个线程进行操作,同步锁synchronized关键字
可见性:一个线程对主内存的修改其他线程可以看见,synchronized和volatile
有序性:一个线程可以观察其他线程指令执行顺序。
如何创建多线程?
- 继承Thread类,重写run方法
- 实现Runnable接口,重写run方法,
- 使用Callable和FutureTask
- 线程池





怎么启动停止线程?
启动线程调用start方法
停止线程,线程的interrupt()方法
调用 interrupt 是如何让线程抛出异常的?
调用Thread.interrupt()可以让线程中断,如果该线程在执行Thread.sleep(),Thread.join(),Object.wait()方法,则会解除阻塞,抛出interruptedException异常。
线程的状态有哪些?
new(初始状态):没有调用start方法
Runnable(可运行状态)调用start方法,
Running(运行中)运行中
Blocked(阻塞状态):等待监视器获取锁
Terminated(终止状态):线程结束
blocked和waiting有啥区别?
blocked是获取锁被阻塞,上一个线程结束会参与锁竞争。
waiting是本线程调用Object.wait()或者Thread.join()方法,必须显示被外部线程唤醒
notify 和 notifyAll 的区别?
notify唤醒一个线程
notifyAll唤醒所有线程,参与锁竞争
怎么保证多线程安全?
- synchronized关键字:可以使用
synchronized
关键字来同步代码块或方法,确保同一时刻只有一个线程可以访问这些代码 - volatile关键字:确保所有变量看到该变量最新值。
- ReentrantLock类
- 线程局部变量:
ThreadLocal
- 原子类:AtomicInteger
- 并发集合:使用
java.util.concurrent
包
Java中有哪些常用的锁?
内置锁synchronized:有无锁,偏向锁,轻量级锁,重量级锁几个级别
高级锁ReetrantLock:可中断,定时,公平,重入
读写锁ReadWriteLock:多个线程访问,一个线程写入
乐观锁:自旋,CAS



synchronized和reentrantlock区别?
synchronized是关键字修饰方法,代码块,reentrantlock修饰代码块,两个都是可重入锁,排它锁
synchronized自动加锁,reetrantlock手动加锁
synchronized是非公平锁,reetrantlock可以是公平锁也可以是非公平锁
synchronized执行原理:两个队列entryList队列和waitSet队列
- 多个线程进入同步代码块,首先进入entryList
- 有一个线程获取到monitor锁后,赋值给当前线程,并且计数器+1
- 如果线程调用wait方法,将释放锁,当前线程置为null,计数器-1,同时进入waitSet等待唤醒,调用notify唤醒后进入entryList竞争锁
- 如果线程执行完毕,同样释放锁,计数器-1,当前线程置为null
reentrantlock执行原理:依赖AQS抽象类
- 可中断
- 设置超时时间
- 公平与非公平
- 可重入
怎么理解可重入锁?
一个线程获取锁后,可以再次获取该锁,不会造成死锁,
synchronized锁升级过程?
无锁,偏向锁,轻量级锁,重量级锁

介绍一下AQS?
AQS是一个抽象类,核心思想是如果被请求的共享资源空闲,将请求的资源加入有效工作线程,将共享资源锁定,如果资源被占用,其他线程访问就被阻塞。
ThreadLocal原理作用?
原理:ThreadLocal是线程里面有一个ThreadLocalMap 变量,这是一个数组,key和value就是存入里面。
作用:是线程隔离,每个线程提高独立的变量副本,避免锁竞争。
悲观锁和乐观锁区别?
悲观锁是悲观的,上来就锁定资源,获取锁后才能操作。
乐观锁是乐观的,不锁资源,先查询再对比,不一样就开启重试机制。
怎么实现乐观锁?
CAS,版本号法,时间戳
内存值,预期值,新值,比较内存中某个值是不是预期值,如果是就修改为新值,不是就不做修改,
不过容易引发aba问题,通过版本号法(时间戳)解决,每次更新加1,如果中间别人修改就可以发现
voliatle作用?
- 保证变量对所有线程可见
- 禁止指令重排序
指令重排序是什么?
语法指令是乱的,不是按顺序加载的,用voliatle可以禁止指令重排序。
什么是公平锁和非公平锁?
公平锁是锁是根据先后顺序获取。
非公平锁是谁先抢到锁就是谁的。
了解线程池原理吗?
存放多个线程的容器,里面线程可以复用,避免频繁创建和销毁线程的开销,提高性能和响应速度
线程池分为:固定线程池,单个线程池,缓存线程池,定时线程池
核心配置包括:核心线程数,工作队列,最大线程数,空闲存活时间,拒绝策略
新任务提交线程池的时候,先进入核心线程池,核心线程池满了,放入任务队列,队列满了,核心线程数小于最大线程数,创建非核心线程,线程池和任务队列都满了,执行拒绝策略
线程池工作满了有哪些拒绝策略?
- 拒绝提交
- 抛出异常
- 抛弃古老任务,执行新任务
- 自定义拒绝策略
如何控制多个线程的执行顺序?
- Thread类的join方法,
- synchronized+wait/notify
- 线程池
线程池的shutdown()和shutdownnow()区别?
shutdown()是进行的任务会继续,没有执行的任务中断,不能再往线程池添加任务。
shutdownnow()是立刻停止,但是不一定可以成功,如果有sleep或者wait或者定时任务要等那些任务执行完成才能成功。
什么是java的内存模型(JMM)?
java内存模型:确保不同线程对共享变量的读写操作具有一致性和可见性,jmm核心目标是确保多线程环境下的可见性,有序性,原子性,主内存,线程内存,线程内存变量修改会同步主内存。
线程的join方法?
join是等待其他线程完成,比如三个线程,每个线程打印1-5,线程1使用join方法,线程2必须等待线程全部完成才会执行自己的方法,join方法会阻塞,直到调用join方法完全执行,可以加入参数,指定最大等待多少秒
分布式锁实现方式有?
MySQL的唯一索引,redis的分布式锁,zookeeper的分布式锁,reddison分布式锁
死锁解决办法?
按顺序执行,加锁按顺序,超时释放