Java 并发基础常见面试题总结
什么是线程和进程
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
Java 程序天生就是多线程程序,我们可以通过 JMX 来看一下一个普通的 Java 程序有哪些线程,代码如下。
public class MultiThread { public static void main(String[] args) { ThreadMXBean threadMXBean= ManagementFactory.getThreadMXBean(); //获取java线程管理MXBean ThreadInfo[] threadInfos=threadMXBean.dumpAllThreads(false,false); for (ThreadInfo threadInfo:threadInfos){ System.out.println("["+threadInfo.getThreadId()+"]"+threadInfo.getThreadName()); } } }
上述程序输出如下(输出内容可能不同,不用太纠结下面每个线程的作用,只用知道 main 线程执行 main 方法即可):
[5] Attach Listener //添加事件 [4] Signal Dispatcher // 分发处理给 JVM 信号的线程 [3] Finalizer //调用对象 finalize 方法的线程 [2] Reference Handler //清除 reference 线程 [1] main //main 线程,程序入口
为什么程序计数器、虚拟机栈和本地方法栈是线程私有的呢?为什么堆和方法区是线程共享的呢?
程序计数器主要有下面两个作用:
1.字节码解释器通过改变程序计数器依次读取指令,从而实现代码的流程控制,如:顺序执行、选择、循环、异常处理。
2.在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了。
堆和方法区
堆和方法区是所有线程共享的资源,其中堆是进程中最大的一块内存,放新创建的对象,方法区主要用于存放被加载的类信息、常量、静态变量、即时编译器编译的代码等数据。
并发: 同一时间段,多个任务都在执行 (单位时间内不一定同时执行);
并行: 单位时间内,多个任务同时执行。
当前任务在执行完 CPU 时间片切换到另一个任务之前会先保存自己的状态,以便下次再切换会这个任务时,可以再加载这个任务的状态。任务从保存到再加载的过程就是一次上下文切换。
如何避免死锁
学过操作系统的朋友都知道产生死锁必须具备以下四个条件:
互斥条件:该资源任意一个时刻只由一个线程占用。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:线程已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
破坏互斥条件
这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥的(临界资源需要互斥访问)。
破坏请求与保持条件
一次性申请所有的资源。
破坏不剥夺条件
占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
破坏循环等待条件
靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。
说说 sleep() 方法和 wait() 方法区别和共同点?
两者最主要的区别在于:sleep 方法没有释放锁,而 wait 方法释放了锁 。
两者都可以暂停线程的执行。
Wait 通常被用于线程间交互/通信,sleep 通常被用于暂停执行。
wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法。sleep() 方法执行完成后,线程会自动苏醒。
为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?
调用start可以启动线程并使线程进入就绪状态,run方法只是thread的一个普通方法调用,还是在主线程执行的。
- Java基础学习总结(104)——多线程、并发、工具类相关的面试题
- Java基础学习总结(108)——Java常见面试题再总结
- 常见JAVA基础面试题1
- 黑马程序员:Java基础总结----线程池及java5的线程并发库
- Java三十个常见面试题总结(一)
- Java并发总结(一):线程基础
- 黑马程序员——Java基础---线程的另一个总结(10)--练习,空中网面试题总结
- Java基础知识之常见关键字以及概念总结
- Java常见面试题总结
- 一些java中常见的基础问题的总结
- JAVA多线程和并发基础面试题
- JAVA研发面试题总结——面向对象基础
- Java基础学习总结(30)——Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结
- JAVA多线程和并发基础面试题
- java并发面试题-基础
- Java并发基础总结
- 常见JAVA基础面试题有哪些
- 常见的Java基础面试题
- java并发基础总结
- 黑马程序员——Java基础--常见对象总结(三)