什么是进程?
进程是程序的一次执行过程。系统运行一个程序即是一个进程从创建运行到销毁的过程。【在 Java 中,启动 main 方法的时候就是启动了一个 JVM 的进程,而 main 方法所在的线程就是这个进程中的一个线程,也称为主线程】
何为线程?
线程与进程相似,线程是一个比进程更小的执行单位。一个进程在执行的过程中可以产生多个线程,与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程都有自己的程序计数器、虚拟机栈、本地方法栈。系统在产生一个线程或是在各个线程之间切换工作的时候,负担要比进程小,所以线程也被称为轻量级进程
进程和线程的关系,区别及优缺点
线程是进程划分的更小的运行单位。线程和进程最大的不同在于各进程是独立的,而各线程不一定,因为同一进程中的线程很有可能会相互影响。线程执行开销小,但不利于资源的管理和保护,而进程则相反
程序计数器为什么是私有的?
程序计数器私有主要是为了线程切换后能恢复到正确的执行位置
程序计数器的作用:1.字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制。2.在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到的位置
虚拟机栈和本地方法栈为什么是私有的?
为了保证线程中的局部变量不被别的线程访问到
- 虚拟机栈:每个 Java 方法在执行前就会创建一个栈帧用于存储局部变量表、常量池引用等这些信息。从方法调用到完成的过程,就对应着一个栈帧在 Java 虚拟机中入栈和出栈的过程
- 本地方法栈:和虚拟机的作用相似,区别是虚拟机栈为虚拟机执行 Java 方法服务,而本地方法栈则为虚拟机使用的 Native 方法服务【Native 方法,就是该方法由非 java 语言实现的方法】
堆和方法区是什么
堆和方法区是所有线程共享的资源,其中堆是进程中最大的一块内存,主要用于存放创建的对象,方法去主要存放已经被加载类的信息、常量、静态变量和编译器编译后的代码等数据
并发和并行的区别
- 并发:两个及两个以上的作业在同一时间段内执行
- 并行:两个及两个以上的作业在同一时刻执行
同步和异步的区别
- 同步:在发出请求后,客户端不能进行其它的操作,直到服务端做完返回客户端,才可以继续进行其它操作
- 异步:在发出请求后,客户端还可以继续进行其它的操作
为什么要使用多线程
现在的系统动不动就需要很高的并发量,而多线程并发编程是比开发高并发系统的基础,利用好多线程可以提高系统整体的并发能力以及性能
使用多线程可能带来的问题是哪些
内存泄漏、死锁、线程不安全等问题
如何理解线程安全和不安全?
- 线程安全:指在多线程的环境下,对于同一份数据,不管有多少个线程同时访问,都能保证这份数据的正确性和唯一性
- 线程不安全:指在多线程的环境下,对于同一份数据,多个线程同时访问可能会导致数据错误或者丢失
说说线程的生命周期和状态
- NEW:初始状态,线程被创建出来但没有被调用 start()
- RUNNABLE:运行状态,线程被调用了 start() 等待运行的状态
- BLOCKED:阻塞状态,需要等待锁释放
- WAITING:等待状态,表示该线程需要等待其它线程做出一些特定动作(通知或者是中断)
- TIME_WAITING:超市等待状态,可以在指定的时间后自行返回
- TERMINATED:终止状态,表示该小城已经运行完成
什么是线程上下文切换
- 主动让出 CPU,比如调用了 sleep(),wait()等方法
- 时间片用完,因为操作系统要放置一个线程或者进程长时间占用 CPU 导致其它线程或者进程死亡
- 调用了阻塞类型的系统终端,比如请求 IO,线程被阻塞
- 被终止或结束运行
什么是线程死锁?
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放,由于线程被一直阻塞,这样程序就不可能正常终止
如何预防和避免线程死锁?
- 预防死锁:1.一次性申请所有的资源。2.占用部分资源的线程再去申请其它资源的时候,如果申请不到,主动释放自己所占用的资源。3.按照某一种顺序申请资源,释放资源则反过来释放
- 避免死锁:破坏请求与保持条件,或者破坏循环等待条件
sleep() 方法和 wait() 方法对比
- 共同点:两者都可以暂停线程的运行
- 区别
- sleep() 方法没有释放锁,而 wait() 方法释放了锁
- wait() 通常用于线程间的交互和通信,sleep() 常用于暂停执行
- wait() 方法调用后,线程不会自动死刑,需要别的线程调用同一对象上的 notify() 或者 notifyAll()方法。sleep() 方法完成后,线程会自动苏醒
- sleep() 是 Thread 类静态本地方法,wait() 则是 Object 类的本地方
为什么 wait() 方法不定义在 Thread 中?
wati() 是让获得对象锁的线程实现等待,会自动释放当前线程占有的对象锁。每个对象都拥有对象锁,既然要释放当前线程占有的对象锁并让它进入 WAITING 状态,自然是操作对应的对象(Object)而不是当前的线程(Thread)
为什么 sleep() 方法定义在 Thread 中?
因为 sleep() 是让当前线程暂停执行,不涉及到对象类,也不需要获得对象锁
可以直接调用 Thread 类的 run 方法码?
调用 start() 方法是启动线程并使线程进入就绪状态,当分配到时间片后就开始运行会自动调用 run() 方法,着才是多线程。而直接执行 run() 方法,会吧 run() 方法当成一个普通方法去执行,相当于还是以单线程的方式来运行