Java多线程编程全面解析:从基础概念到实战应用
1. 多线程编程概述
1.1 什么是线程
线程(Thread)是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。与进程相比,线程具有以下特点:
- 共享资源:同一进程内的多个线程共享进程的内存空间和系统资源
- 轻量级:线程创建、切换和销毁的开销远小于进程
- 并发执行:多线程可以实现真正的并行(多核CPU)或伪并行(单核CPU的时分复用)
1.2 为什么需要多线程
在现代编程中,多线程技术至关重要,主要因为:
- 提高程序响应性:GUI程序使用多线程保持界面响应
- 充分利用多核CPU:现代CPU多为多核心,多线程可以充分发挥硬件性能
- 简化建模:某些问题(如仿真)用多线程模型更自然
- 提高吞吐量:I/O密集型任务中,线程可以在等待I/O时让出CPU
1.3 Java线程模型
Java从语言层面支持多线程编程,主要通过:
java.lang.Thread
类java.lang.Runnable
接口java.util.concurrent
包(JUC)
Java线程与操作系统线程是1:1映射关系,由JVM通过操作系统API实现。
2. 线程创建与启动
2.1 继承Thread类
class MyThread extends Thread {@Overridepublic void run() {System.out.println("线程运行中: " + Thread.currentThread().getName());}
}public class ThreadExample {public static void main(String[] args) {MyThread thread = new MyThread();thread.start(); // 启动线程}
}
特点:
- 简单直接
- 由于Java单继承限制,不够灵活
- 线程与任务耦合
2.2 实现Runnable接口
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Runnable线程: " + Thread.currentThread().getName());}
}public class RunnableExample {public static void main(String[] args) {Thread thread = new Thread(new MyRunnable());thread.start();// Lambda表达式简化new Thread(() -> System.out.println("Lambda线程")).start();}
}
优势:
- 避免继承限制
- 任务与线程解耦
- 便于资源共享
2.3 实现Callable接口(带返回值)
import java.util.concurrent.*;class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {Thread.sleep(1000);return "Callable结果";}
}public class CallableExample {public static void main(String[] args) throws Exception {ExecutorService executor = Executors.newSingleThreadExecutor();Future<String> future = executor.submit(new MyCallable());System.out.println("获取结果: " + future.get());executor.shutdown();}
}
特点:
- 可以返回结果
- 可以抛出异常
- 通常与ExecutorService配合使用
3. 线程生命周期与状态控制
3.1 线程生命周期状态
Java线程在其生命周期中可以处于以下状态:
- NEW:新建但未启动
- RUNNABLE:可运行(可能在运行或等待CPU)
- BLOCKED:等待监视器锁(synchronized)
- WAITING:无限期等待(wait()/join())
- TIMED_WAITING:限期等待(sleep()/wait(timeout))
- TERMINATED:线程终止
Thread thread = new Thread(() -> {try {Thread.sleep(1000); // TIMED_WAITING} catch (InterruptedException e) {e.printStackTrace();}
});
System.out.println(thread.getState()); // NEWthread.start();
System.out.println(thread.getState()); // RUNNABLEThread.sleep(500);
System.out.println(thread.getState()); // TIMED_WAITINGThread.sleep(1000);
System.out