目录一、进程与多线程的背景二、线程的概念与优势三、多线程的效率分析结合图示四、进程和线程的关系经典面试题五、多线程的 API 与实现Java 示例代码示例创建并启动线程执行流分析六、线程的调度与 sleep 方法七、查看 Java 进程内的线程JConsole 工具八、面试注意点九、完整代码示例一、进程与多线程的背景进程process可认为是“任务/执行的计算机”多线程是“并发编程”里的解决方案。服务器场景客户端有多个请求服务器上的程序需要处理 N 个客户端的请求服务端的程序可以采取多进程的解决方案但随着业务规模扩大一个服务器同一时刻需要给更多的客户端提供服务服务器上就要有很多进程且服务器也需要频繁的创建/销毁进程这比较费时间。二、线程的概念与优势线程Thread也叫轻量级进程是为了实现并发编程效果解决多进程模型涉及到的开销大的问题。创建/销毁线程的开销比创建/销毁进程低很多。进程与线程的关系进程包含了线程。进程是操作系统资源分配的基本单位。一个进程中的若干个线程是可以共用操作系统的这些资源的内存、文件。每个线程都是一个“执行流”可以被 CPU 调度执行线程是操作系统调度执行的基本单位。“运行调度”这里的过程更准确的说就是“线程调度”。一个进程中可能包含一个线程也可能包含 N 个线程不能是 0 个。前面说的“进程间调度”里进程只有一个线程的情况称为单线程。进一步理解同一个进程的多个线程之间共用 PCB 的内存指针和文件描述符表但是各自有各自的状态、上下文、优先级、记账信息。线程比进程更轻量轻量体现在创建线程不需要申请那么多资源。进程中的第一个线程创建的时候上述的资源申请都需要。三、多线程的效率分析结合图示多进程方案为了“提高效率”但进程创建销毁开销大比如“桌子”成本高需要拆/建。多线程方案效率提高了且没有付出那么多成本共享“桌子”等资源。线程数目提升效率还能再进一步但当线程数目提升到一定程度效率不一定继续提升甚至可能会降低此时额外的开销较多且 CPU 并行执行的效率也会受限。注意不是说 CPU 20 个核心最多就是 20 个线程不一定的CPU 并行执行提高程序执行速度CPU 核数多能提高程序效率但线程数还受其他因素影响。线程安全问题同一个“桌子”上的“滑稽老铁”共享同一份“烤鸡”此时可能产生冲突多线程编程中多个线程可能同时操作一个数据产生冲突导致程序 bug即“线程安全问题”重点。异常处理如果某个“滑稽”很生气可能要掀桌——如果某个线程运行过程中出现异常且没被正确处理可能导致整个进程都被终止。四、进程和线程的关系经典面试题关系一个进程包含多个线程。区别每个进程有自己独立的资源进程和进程之间不能共享同一个进程的线程之间共享相同的资源。进程之间不会相互影响一个进程挂了其他进程不会有事同一个进程的线程之间特别是容易出现资源访问冲突。进程之间通常不绝对不会有“资源冲突”情况同一个进程的线程之间特别容易出现资源访问冲突。进程是操作系统资源分配的基本单位线程是操作系统调度执行的基本单位。Java 生态中不鼓励使用多进程编程非常鼓励多线程的。五、多线程的 API 与实现Java 示例多线程的相关操作操作系统提供了对应的 APIJava 标准库对操作系统线程的 API 统一封装 → 类/方法Thread。跨平台Java 的Thread类屏蔽了不同操作系统 API 的差异实现跨平台。代码示例创建并启动线程// Demo 例子 public class Demo1 { public static void main(String[] args) { // 1. 创建 Thread 实例 MyThread t new MyThread(); // 2. 启动线程 t.start(); // 不是 t.run() } } class MyThread extends Thread { Override public void run() { while (true) { System.out.println(hello thread); } } }解释run是线程的入口main方法是 Java 程序的入口。t.start()调用操作系统 API在系统内部创建一个线程当这个线程创建好了之后就会自动执行上面重写的run。写代码时不是所有方法都需要手动调用有一类方法回调函数 callback是写了由别人调用比如start触发run。数据结构优先级队列定义一个类实现Comparator/Comparable重写里面的compare/compareTo你定义的函数给别人调用。执行流分析此时这个程序只有一个“执行流”main方法自身对应一个线程即主线程。t.start()又创建了新的线程新的执行流。两个执行流的调度由操作系统负责操作系统调度是“随机”的。六、线程的调度与 sleep 方法线程的调度是操作系统负责调度可以认为是“随机”的。加入sleep让 CPU “休息一下”class MyThread extends Thread { Override public void run() { while (true) { System.out.println(hello thread); // 休息 1000ms 1s try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }sleep是Thread的静态方法。代码示例中加入sleep后输出会交替如hello main、hello thread等因为 1000ms 后线程解除阻塞参与调度谁先谁后不确定。优先级Windows/Linux 上调度器非常复杂还有“实时操作系统”能更精准按优先级调度牺牲其他功能。实际工作中慎用sleep除非你明确知道要“等待”。七、查看 Java 进程内的线程JConsole 工具Java 提供了额外工具看进程内包含的线程JConsolejdk 自带。Java 的调试器。操作打开 IDEA 的Settings→Project Structure确认 JDK 路径然后打开 JConsole选择对应的 Java 进程可看到进程内的线程其他线程是 JVM 自动创建的有特定用途。右键“管理员方式运行” JConsole 可查看更详细信息。八、面试注意点Java 中一般不讨论多进程编程多线程编程中有“父进程/子进程”概念的面试中不要出现这些不严谨的表述。九、完整代码示例class Mythread extends Thread{ Override public void run() { while (true){ System.out.println(Mythread); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class threadDemo { public static void main(String[] args) throws InterruptedException { Thread t new Mythread(); t.start(); while(true){ System.out.println(threadDemo); Thread.sleep(1000); } } }
4.多线程入门必读:为什么线程比进程更“轻量”?
发布时间:2026/5/26 21:41:00
目录一、进程与多线程的背景二、线程的概念与优势三、多线程的效率分析结合图示四、进程和线程的关系经典面试题五、多线程的 API 与实现Java 示例代码示例创建并启动线程执行流分析六、线程的调度与 sleep 方法七、查看 Java 进程内的线程JConsole 工具八、面试注意点九、完整代码示例一、进程与多线程的背景进程process可认为是“任务/执行的计算机”多线程是“并发编程”里的解决方案。服务器场景客户端有多个请求服务器上的程序需要处理 N 个客户端的请求服务端的程序可以采取多进程的解决方案但随着业务规模扩大一个服务器同一时刻需要给更多的客户端提供服务服务器上就要有很多进程且服务器也需要频繁的创建/销毁进程这比较费时间。二、线程的概念与优势线程Thread也叫轻量级进程是为了实现并发编程效果解决多进程模型涉及到的开销大的问题。创建/销毁线程的开销比创建/销毁进程低很多。进程与线程的关系进程包含了线程。进程是操作系统资源分配的基本单位。一个进程中的若干个线程是可以共用操作系统的这些资源的内存、文件。每个线程都是一个“执行流”可以被 CPU 调度执行线程是操作系统调度执行的基本单位。“运行调度”这里的过程更准确的说就是“线程调度”。一个进程中可能包含一个线程也可能包含 N 个线程不能是 0 个。前面说的“进程间调度”里进程只有一个线程的情况称为单线程。进一步理解同一个进程的多个线程之间共用 PCB 的内存指针和文件描述符表但是各自有各自的状态、上下文、优先级、记账信息。线程比进程更轻量轻量体现在创建线程不需要申请那么多资源。进程中的第一个线程创建的时候上述的资源申请都需要。三、多线程的效率分析结合图示多进程方案为了“提高效率”但进程创建销毁开销大比如“桌子”成本高需要拆/建。多线程方案效率提高了且没有付出那么多成本共享“桌子”等资源。线程数目提升效率还能再进一步但当线程数目提升到一定程度效率不一定继续提升甚至可能会降低此时额外的开销较多且 CPU 并行执行的效率也会受限。注意不是说 CPU 20 个核心最多就是 20 个线程不一定的CPU 并行执行提高程序执行速度CPU 核数多能提高程序效率但线程数还受其他因素影响。线程安全问题同一个“桌子”上的“滑稽老铁”共享同一份“烤鸡”此时可能产生冲突多线程编程中多个线程可能同时操作一个数据产生冲突导致程序 bug即“线程安全问题”重点。异常处理如果某个“滑稽”很生气可能要掀桌——如果某个线程运行过程中出现异常且没被正确处理可能导致整个进程都被终止。四、进程和线程的关系经典面试题关系一个进程包含多个线程。区别每个进程有自己独立的资源进程和进程之间不能共享同一个进程的线程之间共享相同的资源。进程之间不会相互影响一个进程挂了其他进程不会有事同一个进程的线程之间特别是容易出现资源访问冲突。进程之间通常不绝对不会有“资源冲突”情况同一个进程的线程之间特别容易出现资源访问冲突。进程是操作系统资源分配的基本单位线程是操作系统调度执行的基本单位。Java 生态中不鼓励使用多进程编程非常鼓励多线程的。五、多线程的 API 与实现Java 示例多线程的相关操作操作系统提供了对应的 APIJava 标准库对操作系统线程的 API 统一封装 → 类/方法Thread。跨平台Java 的Thread类屏蔽了不同操作系统 API 的差异实现跨平台。代码示例创建并启动线程// Demo 例子 public class Demo1 { public static void main(String[] args) { // 1. 创建 Thread 实例 MyThread t new MyThread(); // 2. 启动线程 t.start(); // 不是 t.run() } } class MyThread extends Thread { Override public void run() { while (true) { System.out.println(hello thread); } } }解释run是线程的入口main方法是 Java 程序的入口。t.start()调用操作系统 API在系统内部创建一个线程当这个线程创建好了之后就会自动执行上面重写的run。写代码时不是所有方法都需要手动调用有一类方法回调函数 callback是写了由别人调用比如start触发run。数据结构优先级队列定义一个类实现Comparator/Comparable重写里面的compare/compareTo你定义的函数给别人调用。执行流分析此时这个程序只有一个“执行流”main方法自身对应一个线程即主线程。t.start()又创建了新的线程新的执行流。两个执行流的调度由操作系统负责操作系统调度是“随机”的。六、线程的调度与 sleep 方法线程的调度是操作系统负责调度可以认为是“随机”的。加入sleep让 CPU “休息一下”class MyThread extends Thread { Override public void run() { while (true) { System.out.println(hello thread); // 休息 1000ms 1s try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }sleep是Thread的静态方法。代码示例中加入sleep后输出会交替如hello main、hello thread等因为 1000ms 后线程解除阻塞参与调度谁先谁后不确定。优先级Windows/Linux 上调度器非常复杂还有“实时操作系统”能更精准按优先级调度牺牲其他功能。实际工作中慎用sleep除非你明确知道要“等待”。七、查看 Java 进程内的线程JConsole 工具Java 提供了额外工具看进程内包含的线程JConsolejdk 自带。Java 的调试器。操作打开 IDEA 的Settings→Project Structure确认 JDK 路径然后打开 JConsole选择对应的 Java 进程可看到进程内的线程其他线程是 JVM 自动创建的有特定用途。右键“管理员方式运行” JConsole 可查看更详细信息。八、面试注意点Java 中一般不讨论多进程编程多线程编程中有“父进程/子进程”概念的面试中不要出现这些不严谨的表述。九、完整代码示例class Mythread extends Thread{ Override public void run() { while (true){ System.out.println(Mythread); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class threadDemo { public static void main(String[] args) throws InterruptedException { Thread t new Mythread(); t.start(); while(true){ System.out.println(threadDemo); Thread.sleep(1000); } } }