51. 线程和进程的区别?
线程和进程是操作系统中进行任务调度和资源分配的两个基本概念。
进程:
- 进程是操作系统进行资源分配的基本单位。每个进程都有独立的地址空间,一个进程崩溃后,在保护模式下不会影响到其他进程,因为系统为每个进程提供了独立的内存空间。
- 进程间的通信(IPC,Inter-Process Communication)需要依赖特定的机制(例如管道、消息队列、共享内存等)。
- 进程的创建、销毁和切换所付出的开销较大,因为涉及到地址空间的分配和回收等操作。
- 进程的数量受到系统资源的限制,比如内存、文件描述符等。
线程:
- 线程是进程的执行单元,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位,并且线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器、一组寄存器和栈),但它可以与同属一个进程的其他线程共享进程所拥有的全部资源。
- 同一个进程中的线程间可以直接通信,因为它们共享同一内存空间。
- 线程的创建、销毁和切换比进程要快,因为线程间共享进程的资源,无需额外的资源分配。
- 一个进程可以创建多个线程,这些线程可以并行执行,提高了程序的执行效率和响应速度。
以下是线程和进程的对比表格:
对比项 | 进程 | 线程 |
---|---|---|
资源拥有 | 拥有独立的资源 | 共享进程资源 |
地址空间 | 独立地址空间 | 共享地址空间 |
通信方式 | 需要依赖IPC机制 | 直接读写内存 |
创建、销毁开销 | 较大 | 较小 |
数量限制 | 受系统资源限制 | 相对较多 |
以下是一个简单的Java代码示例,展示如何创建线程:
public class MyThread extends Thread {@Overridepublic void run() {System.out.println("线程运行中...");}public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start(); // 启动线程}
}
在这个示例中,MyThread
类继承了 Thread
类,并重写了 run
方法。当调用 start
方法时,JVM会创建一个线程并执行 run
方法中的代码。这表明了线程在Java中的使用和进程相比的便捷性。
52. 请解释 Java 中的线程生命周期。
在Java中,线程的生命周期定义了线程从创建到消亡可能经历的状态序列。根据Java语言规范,线程的生命周期主要包含以下五个状态:
-
新建(New): 当使用
new
关键字创建一个线程对象时,此时线程处于新建状态。在这个状态下,线程已经分配了必要的资源,但是它还没有开始执行。 -
就绪(Runnable): 一旦调用了线程的
start()
方法,线程就会进入就绪状态。此时线程等待被线程调度器选中并分配CPU时间片执行。在操作系统中,可能存在多个线程处于就绪状态,它们在等待CPU的执行。Thread thread = new Thread(() -> {// 线程任务代码 }); thread.start(); // 进入就绪状态
-
运行(Running): 当线程调度器选中一个就绪状态的线程时,该线程将进入运行状态并开始执行它的任务。需要注意的是,在多核处理器上,可能同时有多个线程处于运行状态。
-
阻塞(Blocked): 在线程运行过程中,由于某些原因(如等待I/O操作、等待获取同步锁等)线程会放弃CPU并暂停执行。此时,线程进入阻塞状态。一旦线程等待的条件满足,它将重新进入就绪状态等待执行。
synchronized (lock) {// 如果其他线程持有锁,当前线程将进入阻塞状态 }
-
终止(Terminated): 线程执行完成后,或者因为某些原因(如异常)而中断执行,线程将进入终止状态。线程一旦终止,就不能再次启动。
以下是线程生命周期的状态转换简表:
状态 | 描述 | 可能的转换状态 |
---|---|---|
新建(New) | 刚创建的线程 | 就绪(Runnable) |
就绪(Runnable) | 等待被调度执行 | 运行(Running) |
运行(Running) | 执行中 | 阻塞(Blocked)、就绪(Runnable)或终止(Terminated) |
阻塞(Blocked) | 等待资源或条件 | 就绪(Runnable) |
终止(Terminated) | 线程执行完成 | - |
了解并掌握线程的生命周期,对于进行多线程编程和调试来说是非常重要的。
领【150 道精选 Java 高频面试题】请go公众号:码路向前 。