Java多线程编程详解
Java多线程编程详解
前言
多线程编程是Java开发中非常重要的内容,能够充分利用多核CPU资源,提高程序的并发能力和响应速度。本文将系统介绍Java多线程的基础知识、常用技术、并发工具类、线程池、常见问题及调优建议,帮助开发者掌握多线程编程的核心要点。
1. 基础概念
1.1 进程与线程
- 进程:操作系统资源分配的最小单位,每个进程拥有独立的内存空间。
- 线程:CPU调度和执行的最小单位,同一进程下的多个线程共享内存资源。
1.2 并发与并行
- 并发(Concurrency):同一时间段内多个任务交替执行。
- 并行(Parallelism):同一时刻多个任务同时执行(多核CPU)。
2. 线程的创建方式
2.1 继承Thread类
public class MyThread extends Thread {@Overridepublic void run() {System.out.println("继承Thread方式创建线程:" + Thread.currentThread().getName());}public static void main(String[] args) {MyThread t1 = new MyThread();t1.start();}
}
2.2 实现Runnable接口
public class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("实现Runnable方式创建线程:" + Thread.currentThread().getName());}public static void main(String[] args) {Thread t1 = new Thread(new MyRunnable());t1.start();}
}
2.3 实现Callable接口 + FutureTask
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println("实现Callable方式创建线程:" + Thread.currentThread().getName());return 100;}public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());Thread t1 = new Thread(futureTask);t1.start();System.out.println("返回结果:" + futureTask.get());}
}
2.4 线程池方式
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(2);executor.execute(() -> System.out.println("线程池方式创建线程:" + Thread.currentThread().getName()));executor.shutdown();}
}
3. 线程的生命周期
- 新建(New)
- 就绪(Runnable)
- 运行(Running)
- 阻塞(Blocked/Waiting/Timed Waiting)
- 死亡(Terminated)
4. 线程同步与互斥
4.1 synchronized关键字
- 修饰实例方法、静态方法、代码块
- 保证同一时刻只有一个线程执行同步代码
public class SynchronizedDemo {private int count = 0;public synchronized void increment() {count++;}public void syncBlock() {synchronized (this) {count++;}}
}
4.2 Lock接口
- 更灵活的同步控制
- 支持公平锁、可重入、可中断
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class LockDemo {private int count = 0;private final Lock lock = new ReentrantLock();public void increment() {lock.lock();try {count++;} finally {lock.unlock();}}
}
4.3 volatile关键字
- 保证变量的可见性,不保证原子性
- 适用于状态标记、单例模式等场景
public class VolatileDemo {private volatile boolean running = true;public void stop() {running = false;}
}
4.4 原子类(Atomic)
- 提供原子操作,避免加锁开销
import java.util.concurrent.atomic.AtomicInteger;public class AtomicDemo {private AtomicInteger count = new AtomicInteger(0);public void increment() {count.incrementAndGet();}
}
5. 常用并发工具类
5.1 CountDownLatch
- 计数器,等待一组线程完成后再继续执行
import java.util.concurrent.CountDownLatch;public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {CountDownLatch latch = new CountDownLatch(3);for (int i = 0; i < 3; i++) {new Thread(() -> {System.out.println(Thread.currentThread().getName() + " 完成任务");latch.countDown();}).start();}latch.await();System.out.println("所有子线程执行完毕");}
}
5.2 CyclicBarrier
- 回环栅栏,允许一组线程互相等待,直到到达某个公共屏障点
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;public class CyclicBarrierDemo {public static void main(String[] args) {CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("所有线程到达屏障,开始执行后续任务"));for (int i = 0; i < 3; i++) {new Thread(() -> {System.out.println(Thread.currentThread().getName() + " 到达屏障");try {barrier.await();} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}).start();}}
}
5.3 Semaphore
- 信号量,控制同时访问某个资源的线程数量
import java.util.concurrent.Semaphore;public class SemaphoreDemo {public static void main(String[] args) {Semaphore semaphore = new Semaphore(2);for (int i = 0; i < 5; i++) {new Thread(() -> {try {semaphore.acquire();System.out.println(Thread.currentThread().getName() + " 获得许可");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release();}}).start();}}
}
5.4 Exchanger
- 线程间数据交换工具
import java.util.concurrent.Exchanger;public class ExchangerDemo {public static void main(String[] args) {Exchanger<String> exchanger = new Exchanger<>();new Thread(() -> {try {String data = "A线程数据";String result = exchanger.exchange(data);System.out.println("A线程收到: " + result);} catch (InterruptedException e) {e.printStackTrace();}}).start();new Thread(() -> {try {String data = "B线程数据";String result = exchanger.exchange(data);System.out.println("B线程收到: " + result);} catch (InterruptedException e) {e.printStackTrace();}}).start();}
}
6. 线程池
6.1 线程池的优势
- 线程复用,减少频繁创建和销毁线程的开销
- 统一管理线程资源,便于监控和调优
- 控制最大并发数,防止资源耗尽
6.2 线程池的核心参数
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- keepAliveTime:空闲线程存活时间
- workQueue:任务队列
- threadFactory:线程工厂
- handler:拒绝策略
6.3 线程池的创建方式
import java.util.concurrent.*;public class ThreadPoolConfigDemo {public static void main(String[] args) {ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<>(100),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());executor.execute(() -> System.out.println("自定义线程池执行任务"));executor.shutdown();}
}
6.4 常用线程池类型
- newFixedThreadPool:固定线程数线程池
- newCachedThreadPool:可缓存线程池
- newSingleThreadExecutor:单线程池
- newScheduledThreadPool:定时任务线程池
7. 常见问题与调优建议
7.1 死锁
- 多个线程互相等待对方释放资源,导致程序无法继续执行
- 解决方法:避免嵌套锁、资源有序分配、使用
tryLock
等
7.2 活锁
- 线程不断地让步和重试,始终无法推进进程
- 解决方法:增加随机等待、限制重试次数
7.3 线程安全问题
- 竞态条件、可见性、原子性问题
- 解决方法:合理使用同步机制、原子类、并发容器
7.4 线程池参数调优
- 根据业务特点合理设置核心线程数、队列长度、拒绝策略
- 监控线程池状态,及时扩容或降级
7.5 其他建议
- 避免在多线程环境下使用非线程安全的类(如
SimpleDateFormat
) - 合理拆分任务,避免单个任务执行时间过长
- 使用高并发包(
java.util.concurrent
)替代手动加锁
8. 总结
Java多线程编程是提升系统性能和并发能力的关键技术。掌握线程的创建、同步、并发工具类和线程池的使用,能够有效应对高并发场景下的各种挑战。实际开发中要注意线程安全、资源管理和性能调优,结合具体业务场景选择合适的并发方案。
本文系统介绍了Java多线程编程的核心知识点,适合初学者入门和有经验开发者查阅参考。