1521 字
8 分钟

多线程

2026-03-11
浏览量 加载中...

一、 线程相关概念#

1.1 程序、进程与线程#

  • 程序:是为完成特定任务、用某种语言编写的一组指令的集合,即我们写的静态代码。

  • 进程

    1. 指​运行中的程序。如启动QQ,操作系统会为其分配独立的内存空间。
    2. 进程是程序的一次执行过程,是动态的,有其产生、存在和消亡的生命周期。
  • 线程

    1. 由​进程创建,是进程的一个实体。
    2. 一个​进程可以拥有多个线程(如一个QQ进程可以同时打开多个聊天窗口)。

1.2 单线程、多线程、并发与并行#

  • 单线程:同一时刻,只允许执行一个线程。
  • 多线程:同一时刻,可以执行多个线程。
  • 并发​:单核CPU实现的多任务。同一时刻,多个任务​交替执行,造成“同时”的错觉。
  • 并行​:多核CPU实现的多任务。同一时刻,多个任务​真正同时执行

二、 线程的创建与使用#

2.1 创建线程的两种方式#

  1. 继承 Thread​​ ,重写 run 方法。
  2. 实现 Runnable​​ 接口,重写 run 方法。

2.2 方式一:继承 Thread 类#

  • 步骤:

    1. 定义一个类继承 Thread。
    2. 重写 run 方法,在其中编写线程要执行的任务。
    3. 创建该类的实例。
    4. 调用实例的 start() 方法启动线程。
  • 注意

    • start() 方法会调用底层的 start0() 方法,使线程进入​可运行状态,由CPU调度执行。
    • 直接调用 run() 方法仅是普通方法调用,​不会启动新线程

2.3 方式二:实现 Runnable 接口#

  • 步骤:

    1. 定义一个类实现 Runnable 接口。
    2. 重写 run 方法。
    3. 创建该类的实例。
    4. 将此实例作为参数传递给 Thread 对象的构造器,创建 Thread 对象。
    5. 调用 Thread 对象的 start() 方法启动线程。
  • 原理​:使用了​代理模式。Thread 类本身实现了 Runnable 接口,其 run 方法会调用传入的 Runnable 对象的 run 方法。

  • 优势

    1. 避免Java单继承的限制。
    2. 更适合多个线程共享同一个资源的场景(只需创建一个 Runnable 实例,传递给多个 Thread 对象)。

三、 线程常用方法#

3.1 第一组常用方法#

  1. setName(String name) / getName():设置/获取线程名称。
  2. start():启动线程,使其进入可运行状态。
  3. run():线程执行体,由JVM调用。
  4. setPriority(int newPriority) / getPriority():设置/获取线程优先级(范围1-10)。
  5. sleep(long millis):静态方法。让当前线程休眠指定的毫秒数。
  6. interrupt():​中断线程,但并非强制结束。通常用于中断正在 sleep 或 wait 的线程,使其抛出 InterruptedException。

3.2 第二组常用方法#

  1. yield() ​:线程的​礼让​。让出CPU,给其他线程执行机会,但礼让成功与否取决于CPU调度,​不一定成功

  2. join() ​:线程的​插队​。调用此方法的线程会阻塞当前线程(如主线程),直到调用者执行完毕,当前线程才继续执行。

    • 应用场景:主线程需要等待子线程执行完特定任务后再继续。

3.3 用户线程与守护线程#

  • 用户线程(工作线程) :线程任务执行完毕或通过通知方式结束。

  • 守护线程​:为工作线程服务。当​所有用户线程结束时,守护线程自动结束

    • 典型例子:垃圾回收线程。
    • 设置方法:线程对象.setDaemon(true); (必须在 start() 前调用)。

四、 线程的生命周期#

JDK中 Thread.State 枚举定义了线程的六种状态:

  1. NEW(新建) :线程对象已创建,但尚未调用 start()。
  2. RUNNABLE(可运行) ​:线程正在JVM中执行,或已就绪等待CPU调度。对应操作系统中的 Ready(就绪)Running(运行) 状态。
  3. BLOCKED(阻塞) :线程等待获取一个监视器锁(如进入 synchronized 代码块失败)。
  4. WAITING(无限等待) :线程等待另一个线程执行特定动作(如 Object.wait())。
  5. TIMED_WAITING(计时等待) :线程在指定时间内等待(如 Thread.sleep(long))。
  6. TERMINATED(终止) :线程执行完毕,已退出。

五、 线程的同步#

5.1 同步的必要性#

在多线程环境下,当多个线程同时访问共享资源(如卖票系统的票数)时,可能导致数据不一致(超卖、重复卖)等问题。

5.2 同步机制 - Synchronized#

保证在任一时刻,最多只有一个线程访问同步代码,确保数据完整性。

  • 同步代码块
synchronized(对象) { // 得到对象的锁才能进入
// 需要同步的代码
}
public synchronized void method() {
// 需要同步的代码
}

5.3 互斥锁#

  • 每个Java对象都有一个互斥锁(Monitor Lock) 标记。

  • synchronized 关键字与对象的互斥锁关联。

  • 锁对象的选择

    1. 对于​非静态同步方法,锁对象默认为 this(当前对象实例)。
    2. 对于​静态同步方法,锁对象默认为 当前类.class。
    3. 对于​同步代码块,锁对象是 synchronized 后括号里指定的对象。
    4. 核心原则​:要求多个线程竞争的​锁对象必须是同一个

5.4 释放锁与不释放锁的操作#

  • 会释放锁

    1. 同步代码块/方法执行完毕。
    2. 同步代码块/方法中遇到 break、return。
    3. 同步代码块/方法中出现未处理的 Error 或 Exception。
    4. 同步代码块/方法中执行了 wait() 方法。
  • 不会释放锁

    1. 调用 Thread.sleep() 或 Thread.yield() 暂停线程。
    2. 其他线程调用了该线程的 suspend() 方法(该方法已废弃,应避免使用)。

5.5 线程死锁#

  • 定义:多个线程都占用了对方所需的锁资源,并且互相等待对方释放,导致所有线程都无法继续执行。
  • 产生条件:互斥使用、不可抢占、请求和保持、循环等待。
  • 解决:在编程中应尽量避免。可以通过规定锁的获取顺序、使用 tryLock 等机制来预防。2

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
多线程
https://blog.tsh520.cn/posts/java笔记本/多线程/
作者
团子和蛋糕
发布于
2026-03-11
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
团子和蛋糕
团子喜欢吃蛋糕!
公告
如果你喜欢,那么欢迎来到我的世界!
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
23
分类
7
标签
14
总字数
85,228
运行时长
0
最后活动
0 天前

目录