一、核心概念理解
首先,我们先搞懂几个关键概念,这是理解多线程的基础:
- 进程:操作系统中运行的一个程序(比如打开的微信、IDEA),是资源分配的基本单位。
- 线程:进程中的执行单元(比如微信同时接收消息、刷朋友圈),是 CPU 调度的基本单位,一个进程可以包含多个线程,线程共享进程的资源。
- 多线程:让一个程序同时执行多个任务(线程),目的是提高程序执行效率(比如下载文件时同时下载多个部分)。
二、Java 实现多线程的两种核心方式
Java 中实现多线程主要有 2 种经典方式,下面给出完整代码示例和解释:
方式 1:继承 Thread 类
Thread 类是 Java 封装好的线程类,继承它并重写run()方法(线程要执行的任务),调用start()方法启动线程(注意:不能直接调用 run (),否则只是普通方法调用,不会创建新线程)。
java
运行
// 1. 继承Thread类 class MyThread extends Thread { // 重写run方法,定义线程要执行的任务 @Override public void run() { for (int i = 0; i < 5; i++) { // Thread.currentThread().getName() 获取当前线程名称 System.out.println(Thread.currentThread().getName() + " 执行:" + i); try { // 模拟任务耗时,让线程休眠100毫秒 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class ThreadDemo1 { public static void main(String[] args) { // 2. 创建线程对象 MyThread thread1 = new MyThread(); MyThread thread2 = new MyThread(); // 给线程命名,方便调试 thread1.setName("线程1"); thread2.setName("线程2"); // 3. 启动线程(核心:调用start(),而非run()) thread1.start(); thread2.start(); // 主线程也会执行代码,观察多线程交替执行效果 System.out.println(Thread.currentThread().getName() + " 主线程执行"); } }输出效果(示例):
plaintext
main 主线程执行 线程1 执行:0 线程2 执行:0 线程1 执行:1 线程2 执行:1 ...(线程1和线程2交替输出,顺序不固定,因为CPU调度是随机的)方式 2:实现 Runnable 接口(推荐)
由于 Java 是单继承,继承 Thread 会限制类的扩展性,因此更推荐实现 Runnable 接口(将 “线程” 和 “任务” 分离),再把 Runnable 对象传给 Thread 类启动。
java
运行
// 1. 实现Runnable接口,定义任务 class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " 执行:" + i); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class ThreadDemo2 { public static void main(String[] args) { // 2. 创建任务对象 MyRunnable task = new MyRunnable(); // 3. 创建线程对象,绑定任务 Thread thread1 = new Thread(task, "线程A"); Thread thread2 = new Thread(task, "线程B"); // 4. 启动线程 thread1.start(); thread2.start(); } }三、多线程核心问题:线程安全
当多个线程同时操作共享资源(比如同一个变量、集合)时,会出现数据错乱,这就是线程不安全。解决方法是加锁(synchronized):
线程不安全示例(未加锁)
java
运行
// 共享资源类 class Counter { private int count = 0; // 未加锁,多线程同时调用会导致count值错乱 public void increment() { count++; System.out.println(Thread.currentThread().getName() + ":count = " + count); } } public class UnsafeThread { public static void main(String[] args) { Counter counter = new Counter(); // 启动10个线程,每个线程调用1次increment for (int i = 0; i < 10; i++) { new Thread(() -> counter.increment(), "线程" + i).start(); } } }问题:输出的 count 可能重复(比如两个线程都输出 count=3),最终 count 可能不到 10。
线程安全解决(加 synchronized 锁)
修改 Counter 类的 increment 方法,加上synchronized关键字(锁住方法,同一时间只有一个线程能执行):
java
运行
class Counter { private int count = 0; // 加synchronized,保证线程安全 public synchronized void increment() { count++; System.out.println(Thread.currentThread().getName() + ":count = " + count); } }效果:count 会从 1 依次递增到 10,无重复、无遗漏。
四、常用线程方法
| 方法 | 作用 |
|---|---|
start() | 启动线程,JVM 会调用该线程的 run () 方法 |
run() | 定义线程执行的任务,不能直接调用 |
sleep(long ms) | 让当前线程休眠指定毫秒数,休眠时不会释放锁 |
join() | 等待该线程执行完毕后,再执行其他线程 |
setName(String name) | 设置线程名称 |
getName() | 获取线程名称 |
setPriority(int p) | 设置线程优先级(1-10,默认 5,优先级高只是更可能被 CPU 调度) |
总结
- Java 实现多线程的核心方式:继承 Thread 类(简单但限制继承)、实现 Runnable 接口(推荐,解耦任务和线程)。
- 启动线程必须调用
start()方法,直接调用run()只是普通方法执行,不会创建新线程。 - 多线程操作共享资源时会出现线程安全问题,核心解决方式是加锁(如
synchronized),保证同一时间只有一个线程操作共享资源。