更新于2021年3月3日09:44:15
常见面试题整理–操作系统篇
Java线程的6种状态详解及创建线程的4种方式 这个挺细的
1.进程和线程
进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例实例实例。程序运行时系统就会创建一个进程,并为它分配资源。
线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源。
2.并发与并行
并发:在操作系统中,某一时间段,几个程序在同一个CPU上运行,但在任意一个时间点上,只有一个程序在CPU上运行。
并行:当操作系统有多个CPU时,一个CPU处理A线程,另一个CPU处理B线程,两个线程互相不抢占CPU资源,可以同时进行,这种方式成为并行。
3.阻塞
阻塞是指调用结果返回之前,当前线程会被操作系统挂起。调用线程只有在得到结果之后才会返回。
4.同步与异步
所谓同步,就是在发出一个调用时,在没有得到结果之前, 该调用就不返回。
异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果
5.JAVA创建线程的四种方式(被问到了,再看一遍)
线程创建的四种方式
继承Thread类创建线程,简单,看懂了。
实现Runnable接口创建线程,多绕了一圈,看懂了。
使用Callable和Future创建线程,没看太懂
使用线程池例如用Executor框架,太长了看不懂。。
6.wait()和sleep()的区别
sleep是线程中的方法,但是wait是Object中的方法。
sleep方法不会释放lock,但是wait会释放,而且会加入到等待队列中。
sleep方法不依赖于同步器synchronized,但是wait需要依赖synchronized关键字。
sleep不需要被唤醒(休眠之后推出阻塞),但是wait需要(不指定时间需要被别人中断)。
7.有哪 6 种常见的线程池?
Fixed/Cached/Scheduled ThreadPool 三种
SingleThreadExecutor/SingleThreadScheduledExecutor 两种
ForkJoinPool 一种
8.ThreadLocal是个啥
知道ThreadLocal嘛?谈谈你对它的理解?
ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。
9.狂神说JUC学习笔记+补充(一)这个挺好的,把前面的知识点都说了一下,而且很细。
Lock和Syncronized的区别:
10.Volatile关键字详解
阿里面试官没想到,一个Volatile我能跟他扯半个小时
写的非常详细,从JMM的角度分析了volatile的原理。
11.什么是死锁?
在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗的讲就是两个或多个进程无限期的阻塞、相互等待的一种状态。
死锁产生的四个条件(有一个条件不成立,则不会产生死锁)
互斥条件:一个资源一次只能被一个进程使用
请求与保持条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
不剥夺条件:进程获得的资源,在未完全使用完之前,不能强行剥夺
循环等待条件:若干进程之间形成一种头尾相接的环形等待资源关系
如果对死锁还不是太熟悉,建议阅读:死锁产生的原因和解锁的方法
12.CAS
一文彻底搞懂CAS实现原理
这篇文章首先通过一个示例(两个线程抢占同一个类中的同一个成员变量data的使用权)介绍了几种保障线程安全的方式:syncronized关键字、使用lock锁、使用Atomic原子类、使用LongAdder原子类。
并且同时说明了用volatile关键字添加在data变量上是无法保证线程安全的,并且说明了原因(volatile关键字仅仅能够保证可见性,无法保证原子性)。
接下来的CAS原理剖析中通过AtomicInteger原子整型类为例分析了CAS底层机制。它的底层是基于Unsafe类实现的,该类直接跟CPU指令通讯
CAS是乐观锁、Syncronized和Lock是悲观锁。
JDK 中 java.util.concurrent.atomic 并发包下,提供了 AtomicStampedReference,通过为引用建立 Stamp 类似版本号的方式,确保 CAS 操作的正确性。
13.线程有哪几种状态(生命周期)
java中每个线程都需经历新生、就绪、运行、阻塞和死亡五种状态,线程从新生到死亡的状态变化称为生命周期。
1.新建状态:使用 new Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。
2.就绪状态:调用了start()方法之后,该线程就进入就绪状态(就绪队列中),等待JVM里线程调度器的调度。
3.运行状态:执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
4.阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。
5.死亡状态:一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
14.手动初始化线程池的参数 线程池之ThreadPoolExecutor概述
序号 | 名称 | 类型 | 含义 |
---|---|---|---|
1 | corePoolSize | int | 核心线程池大小 |
2 | maximumPoolSize | int | 最大线程池大小 |
3 | keepAliveTime | long | 线程最大空闲时间 |
4 | unit | TimeUnit | 时间单位 |
5 | workQueue | BlockingQueue<Runnable > |
线程等待队列 |
6 | threadFactory | ThreadFactory | 线程创建工厂 |
7 | handler | RejectedExecutionHandler | 拒绝策略 |