多线程常见面试题
1. 并发的三要素
- 原子性: 原子性是指再一次或者多次的操作过程中,要么同时成功,要么同时失败
- 可见性:可见性是指多个线程同时操作一个共享资源的时候,其中一个线程对共享资源进行修改,其他线程立马可以得知修改的结果
- 有序性:有序性是指程序的执行顺序按照代码的先后顺序来执行
2.实现可见的方法那有些
- synchronized或者lock: 保证同一时间只有一个线程对变量进行修改,释放锁之前把修改的值刷新到主内存,就可以实现可见性
3.多线程的优点
- 能够发挥多核CPU的优势: 多线程可以真正的发挥出多核CUP的优势,充分的利用CPU采用多线程的方式去完成几件事情而互不干扰
- 防止阻塞: 单核CPU无法发挥出多线程的优势,反而在单核CPU上运行多线程会降低程序整体的效率
- 便于建模: 个人感觉跟SpringBoot的微服务很像,把一个大的项目拆分成多个小项目,每个微服务执行自己的功能,而便于建模就是把一个大的任务拆分成多个小任务,然后分别简历程序模型,并通过多线程分别运行这个个任务
4.创建线程的方式有哪些
- 继承Thread类创建线程
- 创建线程池
- 通过Callable和Futrue创建线程
- 实现Runnable接口来创建线程
5.什么是Future
- future是一个未来对象,里边保存该线程的处理结果,就像我们去菜鸟驿站拿快递,凭着取件码随时都能去取
6.Runnable和Callable的区别
- Runnable重写的是run()方法,Callable重写的是Call()方法
- Callable的任务执行完成后可返回值,Rnnable不可返回值
- Call方法可以抛异常,Run方法不行
- 运行Callable任务的时候可以拿到一个Future对象,代表异步计算的结果. 通过futrue对象可以了解任务执行情况,可以取消任务执行,还可以获取执行结果
7.线程和进程的却别
- 线程是程序执行的最小单位,而进程是系统操作分配资源的最小单位
- 一个进程由一个或者多个线程组成,线程是一个进程中代码的不同执行路线
- 进程之间是相互独立的,但同一个进程下的线程之间是共享程序的内存空间纪一些进程及的资源,某个进程内的线程其他进程是不可见的
- 调度和切换:线程上下文切换比进程上下文切换要快的多
8.什么是上下文切换
- 是指当前任务执行一个时间片之后就会切换到下一个任务,但是在切换前会保存上一个任务的状态,以便下次切换回来的时候可以再次加载这个任务的状态,从任务保存再到加载这就是一次上下文的切换
9.创建线程的三种方式的对比
- 实现Runnable和Callable接口比继承Thread类更有优势
- 适合多个线程进行资源共享
- 可以避免java中单继承的限制
- 线程类已经继承Thread类,所以不能继承其他的父类
- 相比Runnable和Callable,Thead如果需要访问当前线程,不需要使用Thread.currentThread()方法,而直接使用this即可获得当前线程,Runnable和Callable就得靠Thread.currentThread()方法去获取当前线程
- 增加程序的健壮性,代码和数据的独立性
- 线程池中只能放Runnable和Callable接口的实现类,不能直接放入继承Thread的类
- 参考第六题Runnable和Callable的区别
10.Java线程具有五中基本状态
https://www.cnblogs.com/marsitman/p/11228684.html
- new(新建状态) : 当线程被创建后,即进入了新建状态 比如:Thread thread = new Thread();
- runnable(就绪状态) : 就是调用线程的start()方法后,这时候线程等待CPU分配资源阶段,谁抢到了CPU资源,谁就开始干活
- running(运行状态) : 当就绪的线程被调度并且获得了CPU资源的时候,便进入运行状态,run方法定义了线程的操作和功能
- blocked(阻塞状态) : 在运行状态的时候,可能因为某种原因导致线程变得堵塞,比如: sleep(),wait()之后线程就出于阻塞状态,这是就需要其他机制将出于阻塞状态的线程唤醒,比如调用notify()和notifyAll(),被唤醒的线程不会立刻进入运行状态,需要再次等待CPU分配资源后在进入运行状态
- dead(销毁状态) : 如果线程正常执行完毕后或者线程提前被强制性的终止或者出现异常导致结束,那么线程就会被销毁,释放资源