Java 多线程基础

· 7 min read

多线程:充分利用计算机资源,同时执行不同的操作


一、操作系统简介

操作系统的作用

帮助上层应用程序屏蔽掉硬件的丑陋接口。

操作系统的发展史

  1. 手工操作
  2. 批处理系统
  3. 多道批处理
  4. 分时系统
  5. 实时系统

进程和线程

  • 进程:正在执行的程序,其实就是一块内存区域,内部存储着程序的资源
  • 线程:程序被 CPU 调度的最小单位

二、Java 多线程实现

Java 中创建线程的两种方式:

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

核心方法

方法说明
run()线程执行时要执行的代码
start()启动一个线程

三、线程的生命周期

状态进入方式退出方式
NEWnew Thread()start()
RUNNABLEstart()、唤醒、超时、获得锁时间片用完、yield()、等待资源
BLOCKED等待 synchronized获得锁
WAITINGwait()join()LockSupport.park()notify()notifyAll()interrupt()
TIMED_WAITINGsleep()wait(timeout)join(timeout)时间到、被唤醒、interrupt()
TERMINATEDrun() 执行完毕、异常退出-

四、线程中的相关方法

方法说明
sleep()睡眠,让线程暂停执行
setPriority()设置优先级 1~10,默认为 5
join()让主线程等待这个子线程执行完毕
yield()让出 CPU,让别人执行一下
interrupt()打断正在睡眠中的线程

五、线程同步

线程同步是指多个线程访问共享资源时,确保同一时刻只有一个线程能够访问,避免数据不一致的问题。

当多个线程共享同一个资源时,可以在某一个线程访问到这个资源时把这个资源暂时封锁,等待执行结束后释放这个锁,其他线程才可以进行执行。

等待其他线程释放锁,让线程更加安全。

实现方式

  1. 在方法声明上添加 synchronized 关键字
  2. 在方法内部使用 synchronized 代码块(更灵活,推荐)
  3. 手动上锁 ReentrantLock(结束要释放锁)

六、死锁

死锁是指两个或多个线程互相持有对方需要的资源,导致所有线程都无法继续执行的状态。


七、生产者消费者模型

生产者消费者模型是多线程通信的经典设计模式,核心解决:生产者生产数据、消费者消费数据,两者速度不一致时,通过缓冲区解耦,保证线程安全、避免数据丢失 / 重复消费。

核心工具

  • BlockingQueue 阻塞队列(JDK 封装好的线程安全队列,自动实现等待 / 唤醒,开发首选)

    • 当队列中没有数据时,需要拿数据的线程会被阻塞,直到队列中有数据才继续工作
  • AtomicInteger = 线程安全的 int 计数器

    • Java 提供的原子操作类,专门解决多线程下 i++ 不安全的问题

八、线程池

线程的创建和销毁是比较消耗性能的操作,线程池正是为解决此问题而生。

作用

  1. 复用线程,不频繁创建销毁,省资源
  2. 控制并发数,防止线程爆炸卡死
  3. 统一管理任务,提高响应速度

Java 线程池五大核心参数

  1. 核心线程数 corePoolSize
  2. 最大线程数 maximumPoolSize
  3. 空闲超时 keepAliveTime
  4. 时间单位 unit
  5. 阻塞队列 workQueue

四种拒绝策略

拒绝策略说明
AbortPolicy直接抛异常(默认)
CallerRunsPolicy交给调用者线程执行
DiscardPolicy丢弃当前任务
DiscardOldestPolicy丢弃队列中最老的任务

4 种常用内置线程池

  1. newFixedThreadPool — 固定线程数
  2. newSingleThreadExecutor — 单线程串行
  3. newCachedThreadPool — 弹性缓存线程(空闲自动回收)
  4. newScheduledThreadPool — 定时 / 周期任务