前言
线程是Java语言中不可获取的重要功能,它们能使复杂的异步代码变得简单,从而极大地简化了复杂系统的开发。此外,要想充分发挥多核处理器系统的强大计算能力,最简单的方式就是使用线程。
并发编程的背景
- 为什么需要并发编程:当前CPU的计算能力强大且成本相对较低,采用并发编程可以更好的利用CPU的高性能,提升复杂应用程序的性能;也能有效降低程序的开发和维护成本(简化异步事件的处理、充分利用CPU的能力)
- 计算机背景知识
- 计算机体系架构中,CPU、内存、I/O设备这三者的计算速度存在很大的差异,CPU>>内存>>>>I/O设备;
- 为了合理利用CPU,平衡三者的速度差异,计算机体系、操作系统、编译程序分别做出了贡献,主要体现为:
- 计算机体系:CPU增加了缓存,以均衡与内存的速度差异
- 操作系统:增加了进程、线程,可以分时复用CPU,以均衡CPU与I/O设备的速度差异
- 编译程序:优化指令执行顺序,使缓存能够得到更加合理地利用
并发编程带来的问题
安全性、活跃性、性能问题
- 安全性主要概括为三大问题:可见性、原子性、有序性;
- 可见性:是指变量修改的可见性。即一个线程对共享变量的修改,其他线程能够立马看到。(由于共享变量都在存放在共享内存中,而每个线程有一个本地缓存,线程操作数据都会先将变量加载到本地缓存中再操作,所以就可能会产生变量不可见的问题)
- 原子性:是指内存模型操作的原子性。指一个或者多个操作在CPU执行的过程中不会因为切换线程而导致中断的特性。(由于CPU的线程数有限,在运行应用程序时,会随时切换线程)
- 有序性:是指代码执行的有序性。即如果下一步操作需要依赖上一步的操作结果,那么必须保证其按顺序执行。(JVM会对代码进行重排序以提升效率)
- 活跃性问题主要有:死锁、活锁、线程饥饿问题
- 线程饥饿:线程因其他线程一直抢占CPU资源,导致一直得不到执行;
- 死锁:是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。死锁的四个必要条件:互斥(进程在某一时间独占资源)、请求与保持(进程因请求资源造成阻塞时,已占有资源不释放)、不可抢占(进程未使用完的资源不能被剥夺)、循环等待(线程A等待线程B占有的资源,线程B等待线程A占有的资源)
- 活锁:任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败。例如:死循环、自旋锁。
- 性能问题主要有:锁的竞争、线程上下文切换、线程阻塞、内存同步等
线程相关概念
- 什么是线程和进程:进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元;一个程序至少有一个进程,一个进程至少有一个线程。
- 用户线程和守护线程:
- 用户(User)线程就是用来运行程序代码的线程,如:运行程序的线程;
- 守护(Daemon)线程就是用来为用户线程提供服务的辅助线程,如:垃圾回收线程。守护线程通过Thread.setDaemon(true)设置,必须在Thread.start()之前调用。程序不一定需要守护线程,但当用户线程全都结束时,守护线程也会全都自动结束
- 线程安全性:当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的。
- 线程上下文切换:多线程需要共同使用服务器的CPU资源,当多线程数超过系统给程序分配的CPU数量时,为了保证每个线程都能被执行,需要轮转使用CPU。不同线程切换使用CPU所产生的切换数据叫上下文切换
- 线程同步和互斥
- 线程同步:线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到得到消息后才被唤醒。
- 线程互斥:线程互斥是指对于共享的进程系统资源,同一时刻最多只允许一个线程访问,其他线程必须等待占用者释放资源后才能访问。
- 线程封闭:仅在单线程内访问数据,不对其他线程共享。这种技术被称为线程封闭。常见应用:JDBC的Connection对象。
线程的生命周期

- NEW(初始化状态):创建Thread对象
- RUNNABLE(可运行/运行状态):调用线程对象的 start() 方法
- BLOCKED(阻塞状态):线程等待 synchronized 的隐式锁。线程调用阻塞式 API 时,只会使操作系统中的线程转换到休眠状态,JVM中的线程不会发生变化。
- WAITING(无时限等待):(1)获得 synchronized 隐式锁的线程,调用无参数的
Object.wait()
方法;(2)调用无参数的Thread.join()
方法;(3)调用LockSupport.park()
方法
- TIMED-WAITING(有时限等待):(1)调用带超时参数的
Thread.sleep(long millis)
方法;(2)获得 synchronized 隐式锁的线程,调用带超时参数的Object.wait(long timeout)
方法;(3)调用带超时参数的Thread.join(long millis)
方法;(4)调用带超时参数的LockSupport.parkNanos(Object blocker, long deadline)
方法;(5)调用带超时参数的LockSupport.parkUntil(long deadline)
方法
- TERMINATED(终止状态):(1)线程执行完run方法;(2)执行run方法的时候抛出异常;(3)调用interrupt方法强制中断run方法
Thread基本方法说明
构造方法
| public Thread(Runnable target) { |
| init(null, target, "Thread-" + nextThreadNum(), 0); |
| } |
属性设置
| |
| public void setContextClassLoader(ClassLoader cl) {...} |
| |
| public final void setDaemon(boolean on) {...} |
| |
| public final synchronized void setName(String name) {...} |
| |
| public final void setPriority(int newPriority) {...} |
管理生命周期
| |
| public synchronized void start() {...} |
| |
| public final synchronized void join(long millis) throws InterruptedException {...} |
| |
| public static native void yield(); |
| |
| public static native void sleep(long millis) throws InterruptedException; |
| |
| public void interrupt() {} |
检测状态
| |
| public final native boolean isAlive(); |
| |
| public final boolean isDaemon() {...} |
| |
| public boolean isInterrupted() {...} |
获取当前线程
| public static native Thread currentThread(); |
创建线程
(1)继承Thread类重写run方法;(2)实现Runnable接口;(3)实现Callable接口;(4)通过线程池的线程工厂方法创建
| |
| public static void main(String[] args) { |
| TestThread testThread=new TestThread(); |
| testThread.start(); |
| |
| } |
| static class TestThread extends Thread{ |
| @Override |
| public void run(){ |
| System.out.println("hello world"); |
| } |
| } |
| |
| Thread thread=new Thread(()->{ |
| System.out.println("hello world"); |
| }); |
| thread.start(); |
| |
| FutureTask futureTask=new FutureTask(()->"hello world"); |
| Thread thread=new Thread(futureTask); |
| thread.start(); |
| |
| ExecutorService executor=new ThreadPoolExecutor(8,8,1L |
| ,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(8)); |
| executor.submit(()->"hello world"); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义