一、基础概念
1.进程与线程
进程:操作系统资源分配的基本单位,拥有独立的内存空间(如代码段、堆、方法区)。
线程:进程内的执行单元,是CPU调度的最小单位,共享进程资源(如堆内存),但拥有独立的栈空间。
单线程 vs 多线程:单线程按顺序执行任务,多线程通过并发/并行提升性能(需多核CPU支持并行)。
2.并发与并行
并发:单核CPU通过时间片轮转模拟多任务交替执行。
并行:多核CPU同时执行多个任务。
二、线程的创建与启动
Java提供两种核心方式创建线程:
1.继承Thread类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程执行中:" + Thread.currentThread().getName());
}
}
// 启动线程
public static void main(String[] args) {
MyThread t = new MyThread();
t.start(); // 启动新线程
}
特点:简单但受限于单继承。
2.实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("任务执行中:" + Thread.currentThread().getName());
}
}
// 启动线程
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
}
优势:避免单继承限制,支持资源共享。
3.其他方式
Lambda表达式(Java 8+):简化代码,如 new Thread(() -> System.out.println("Lambda线程")).start();
Callable接口:支持返回值和异常处理,需配合Future使用。
三、线程生命周期与状态
线程状态包括:
NEW(新建) → RUNNABLE(就绪) → RUNNING(运行) → BLOCKED(阻塞) → WAITING(等待) → TIMED_WAITING(计时等待) → TERMINATED(终止)。
关键方法:
join():等待线程结束(如主线程等待子线程完成)。
setPriority():设置优先级(1-10,默认5)。
sleep():暂停线程执行(单位:毫秒)。
setDaemon(true):设为守护线程(主线程退出时自动终止)。
四、线程同步与并发安全
多线程共享资源时需解决数据竞争问题:
1.同步代码块
synchronized (lockObject) {
// 临界区代码
}
原理:基于对象监视器锁(Monitor Lock),确保同一时间仅一个线程访问临界区。
2.同步方法
public synchronized void method() {
// 同步方法体
}
等价于:synchronized (this)。
3.Lock接口
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// 临界区操作
} finally {
lock.unlock(); // 必须释放锁
}
优势:支持公平锁、可中断锁等高级特性。
4.原子类
AtomicInteger counter = new AtomicInteger(0);
int value = counter.incrementAndGet(); // 原子递增
原理:基于CAS(Compare-And-Swap)实现无锁并发。
五、线程池技术
作用:复用线程,减少创建/销毁开销,提升性能。
1.核心参数
corePoolSize:核心线程数(常驻)。
maximumPoolSize:最大线程数。
workQueue:任务队列(如LinkedBlockingQueue)。
RejectedExecutionHandler:拒绝策略(如丢弃、抛异常)。
2.创建线程池
ExecutorService executor = Executors.newFixedThreadPool(5); // 固定线程池
executor.submit(() -> System.out.println("任务提交"));
executor.shutdown(); // 优雅关闭
3.线程池类型
FixedThreadPool:固定线程数。
CachedThreadPool:弹性线程池(自动回收空闲线程)。
ScheduledThreadPool:支持定时任务。
六、高级并发工具
1.CountDownLatch
CountDownLatch latch = new CountDownLatch(3);
// 等待3个线程完成
latch.await();
用途:主线程等待多个子线程完成。
2.CyclicBarrier
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("所有线程就绪"));
// 多个线程相互等待后同步执行
barrier.await();
用途:多线程协同执行任务。
3.ConcurrentHashMap
线程安全哈希表,通过分段锁(JDK 1.7)或CAS(JDK 1.8)实现高并发性能。
七、注意事项
避免死锁:按固定顺序获取锁,或使用tryLock()超时机制。
线程中断:通过interrupt()方法中断线程,需配合状态检查(如isInterrupted())。
资源竞争:减少锁粒度,优先使用无锁数据结构(如ConcurrentLinkedQueue)。
示例:多线程售票系统
class TicketSystem implements Runnable {
private int tickets = 100;
private final Object lock = new Object();
@Override
public void run() {
while (true) {
synchronized (lock) {
if (tickets <= 0) break;
System.out.println(Thread.currentThread().getName() + "售出第" + tickets--);
}
try {
Thread.sleep(100); // 模拟售票耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(new TicketSystem(), "窗口1");
Thread t2 = new Thread(new TicketSystem(), "窗口2");
t1.start();
t2.start();
}
}
输出:多个线程交替售出票号,保证数据一致性。
通过合理使用线程创建、同步机制和并发工具,Java多线程编程可显著提升程序性能,但需谨慎处理资源竞争与线程安全问题。