Java多线程面试题
1. 多线程的死锁
造成死锁前提:
-
互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
-
不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
-
请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占用。
-
循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路
上述四个前提条件都满足,才会造成死锁
在实际开发中, 避免死锁, 只需要把上述四个条件任意一个打破,就可以避免死锁
2. 多线程三种实现方法的区别
-
采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
-
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。
-
Runnable和Callable的区别:
(1)Callable规定的方法是call(),Runnable规定的方法是run().
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值得
(3)call方法可以抛出异常,run方法不可以,因为run方法本身没有抛出异常,所以自定义的线程类在重写run的时候也无法抛出异常
(4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
start()和run()的区别
-
start()方法用来,开启线程,但是线程开启后并没有立即执行,他需要获取cpu的执行权才可以执行
-
run()方法是由jvm创建完本地操作系统级线程后回调的方法,不可以手动调用(否则就是普通方法)
3. 线程的生命周期
-
新建(通过构造)
-
就绪(通过start()方法)
-
执行(通过资源调度,获取资源)
-
阻塞
-
死亡
4. 进程 ,线程 概念
进程:
程序: 一堆代码集合, 存在硬盘
运行程序: 运行代码, 开辟内存空间 (CPU, 内存) 程序状态: 运行 称为一个进程
进程: 程序的运行状态 查看进程: ctrl + alt + delete 点击查看任务,
程序运行时,产生一个进程, 分配内存空间, 进程之间的内存空间隔离
线程:
线程是CPU调度和分派的基本单位
线程是进程内部单一的一个顺序控制流。
一个进程包含多个线程
一个进程关闭, 这个进程中所有的线程关闭了
但是一个线程关闭, 不会影响进程关闭
多个线程之间是抢占式的
多线程是实现并发机制的一种有效手段。