【线程】尤其是【多线程】也是每个程序员都绕不开的一个概念,本篇文章就是尝试换一种思路或者说角度来重新梳理这个概念。
首先我们先理解线程的概念
线程是处理器调度的基本单位,是程序执行的最小单位,每个程序都有一个入口和一个出口,对于单线程,程序执行过程中的任何制定时刻,都只有一个单独的执行点,而多线程则意味着同一时刻,多个执行点同时执行。
经常会被拿来与【进程】做对比
1两者粒度层级不同,进程属于操作系统级,线程则属于处理器级
2不同进程代码、内部数据、状态都是完全独立的,一个进程就是一个执行中的程序;而一个 程序内的多线程共享一块内存和资源,有可能互相影响,比如争夺资源。
3线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换负担比进程切换的要小。
4多核处理器可以并发运行不同的线程,否则任何时刻只有一个线程在运行。这也是为什么手机/电脑在追求性能时都需要多核多线程。
接着我们用「摸鱼」的轻松方式来理解 Java 线程这个硬核概念。
1. 线程的本质:打工人的分身术
- 线程是程序执行的最小单位,一个进程(主程序)可以开多个线程(小号)
- 所有线程共享同一个进程的内存空间(相当于摸鱼小号和你的主账号共用电脑)
- 主线程(上班):你正儿八经在工位敲代码,这是主线程的任务(比如处理用户请求)。
- 子线程(摸鱼):你偷偷打开摸鱼网站看八卦,这是子线程的任务(比如刷微博)。
- 多线程并行:你的大脑同时在“写代码”和“刷微博”之间快速切换(CPU时间片轮转)。
2. 线程生命周期(新建New、就绪Runnable、运行Running、阻塞Blocked(包含Waiting和Timed Waiting)、终止Terminated):打工人的摸鱼姿势
- New(上班):新的一天开始了,你愉快地来上班
- Runnable(摸鱼待命中):你开着摸鱼页面,但暂时没看(线程就绪,等待CPU调度)。
- Running(愉快地划水):没人没事打扰
- Blocked(摸鱼被阻):老板突然路过,你火速切回IDE(线程因锁/I/O阻塞暂停)。
- Terminated(下班摸鱼结束):下班时间到,摸鱼任务自然终止(线程执行完毕)。
代码类比:
// 摸鱼全过程代码演示
new Thread(() -> { // 新建摸鱼小号(NEW状态)
start(); // 准备摸鱼(RUNNABLE状态)
synchronized(老板监控) { // 如果老板在盯屏幕→阻塞(BLOCKED状态)
Thread.sleep(3000); // 假装工作→实际摸鱼(TIMED_WAITING状态)
}
System.out.println("摸鱼成功!"); // 摸鱼结束(TERMINATED状态)
});
3.创建线程的两种方式:如何科学划水
方式一继承Thread类(死板摸鱼)
代码类比
class 摸鱼小号 extends Thread {
public void run() {
while(true) {
if (!老板出现) 刷微博();
}
}
}
// 缺点:Java只能单继承,占用了宝贵的"爹位"
方式二实现Runnable接口(灵活摸鱼)
代码类比
class 摸鱼任务 implements Runnable {
public void run() {
悄悄打开手游();
}
}
new Thread(new 摸鱼任务()).start(); // 推荐!不占继承位,还能用lambda表达式
4. 线程同步:摸鱼与工作的博弈
-
锁机制(会议室争夺)
你和同事都想用会议室(共享资源),但只有一人能进(互斥锁)。
代码版:synchronized
或ReentrantLock
控制临界区访问。
// 方案1:synchronized锁
synchronized(会议室) {
开会(); // 一次只允许一个线程
}
// 方案2:Lock锁
Lock lock = new ReentrantLock();
lock.lock();//先加个锁
try {
偷吃零食();
} finally {
lock.unlock(); // 办完事情再解锁
}
-
死锁(互相卡死)
你等同事用完打印机,同事等你的U盘,两人僵持(资源循环等待)。
代码版:避免嵌套锁或设置超时(tryLock
)。 -
线程通信(暗号对接)
你发消息问同事:“老板走了吗?”(wait/notify
),同事回复:“安全了!”(唤醒线程)。
5. 线程池:摸鱼流水线管理
- 核心线程(固定摸鱼工位):公司允许的日常摸鱼额度(
corePoolSize
)。 - 临时线程(突击情况):双十一突然来了需求,临时工顶上(
maximumPoolSize
)。 - 摸鱼超时回收:如果摸鱼太久(
keepAliveTime
),工位会被回收(线程销毁)。
总结:线程就是「光明正大摸鱼」的艺术
- 核心思想:通过“假装工作”(并行处理)提升整体效率(吞吐量)。
- 程序员忠告:
- 摸鱼太多(线程数爆炸)会被老板发现(OOM)!
- 摸鱼要低调(避免锁竞争),摸鱼姿势要优雅(合理使用线程池)!
- 千万千万不要耽误主线程
(注:本类比仅供学习,实际编码请遵守公司摸鱼守则——哦不,是多线程最佳实践。)
【注】:面向对象是对现实世界的理解和抽象,它们之间肯定是可以相互关联的,或者每一种思想或机制都可以在现实世界找到类似的注解,所以才想着整理了这一系列【深入浅出之编程概念】,哈哈哈^_^
如有不合适地方,欢迎各位程序员指正或者友好讨论