Java多线程编程是实现并发程序的重要技术,能够有效提升程序性能和资源利用率。以下是Java多线程的核心知识点及实践指南:
一、线程创建与管理
创建线程的三种方式
继承Thread类:
java
class MyThread extends Thread { public void run() { System.out.println("Thread running"); } } new MyThread().start();实现Runnable接口(推荐,避免单继承局限):
java
class MyTask implements Runnable { public void run() { System.out.println("Task running"); } } new Thread(new MyTask()).start();实现Callable接口(支持返回值):
java
class MyCallable implements Callable<String> { public String call() throws Exception { return "Callable result"; } } FutureTask<String> futureTask = new FutureTask<>(new MyCallable()); new Thread(futureTask).start(); System.out.println(futureTask.get()); // 获取返回值
线程池(ThreadPoolExecutor)
手动创建线程池(推荐方式):
java
int corePoolSize = 5; int maxPoolSize = 10; long keepAliveTime = 1L; BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100); ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue ); executor.execute(() -> System.out.println("Task executed"));常用线程池类型:
FixedThreadPool:固定线程数,适合负载较重的服务器。
CachedThreadPool:线程数按需创建,适合短期异步任务。
SingleThreadExecutor:单个线程顺序执行任务。
二、线程同步与锁机制
synchronized关键字
同步方法:
java
public synchronized void syncMethod() { // 同步代码 }同步代码块:
java
public void method() { synchronized(this) { // 同步代码 } }
ReentrantLock(可重入锁)
java
private final Lock lock = new ReentrantLock(); public void performTask() { lock.lock(); try { // 临界区代码 } finally { lock.unlock(); } }ReadWriteLock(读写锁)
java
private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); public void readData() { rwLock.readLock().lock(); try { // 读操作 } finally { rwLock.readLock().unlock(); } } public void writeData() { rwLock.writeLock().lock(); try { // 写操作 } finally { rwLock.writeLock().unlock(); } }原子类(Atomic Classes)
java
private AtomicInteger count = new AtomicInteger(0); public void increment() { count.incrementAndGet(); // 原子操作 }
三、线程间通信
wait()/notify()机制
java
synchronized(lock) { while (conditionNotMet) { lock.wait(); // 释放锁并等待 } // 执行任务 lock.notifyAll(); // 唤醒所有等待线程 }Condition接口(配合Lock使用)
java
private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void awaitMethod() throws InterruptedException { lock.lock(); try { condition.await(); // 类似wait() } finally { lock.unlock(); } } public void signalMethod() { lock.lock(); try { condition.signal(); // 类似notify() } finally { lock.unlock(); } }
四、并发工具类
CountDownLatch(倒计时门闩)
java
CountDownLatch latch = new CountDownLatch(3); // 线程完成任务后调用latch.countDown() latch.await(); // 主线程等待所有任务完成CyclicBarrier(循环屏障)
java
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads reached barrier")); // 线程调用barrier.await()等待其他线程Semaphore(信号量)
java
Semaphore semaphore = new Semaphore(5); // 允许5个线程同时访问 semaphore.acquire(); // 获取许可 try { // 访问资源 } finally { semaphore.release(); // 释放许可 }Exchanger(交换器)
java
Exchanger<String> exchanger = new Exchanger<>(); // 线程A String dataA = exchanger.exchange("Data from A"); // 线程B String dataB = exchanger.exchange("Data from B");
五、高级并发特性
CompletableFuture(异步编程)
java
CompletableFuture.supplyAsync(() -> "Hello") .thenApplyAsync(s -> s + " World") .thenAccept(System.out::println);Fork/Join框架(分治任务)
java
class MyTask extends RecursiveTask<Integer> { protected Integer compute() { // 分解任务并合并结果 } } ForkJoinPool pool = new ForkJoinPool(); pool.invoke(new MyTask());ThreadLocal(线程局部变量)
java
private static ThreadLocal<SimpleDateFormat> dateFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
六、避免常见问题
死锁预防:按固定顺序获取锁,使用尝试锁(
tryLock())。资源竞争:最小化同步代码块,使用并发集合(如
ConcurrentHashMap)。内存可见性:使用
volatile变量或原子类确保修改可见性。线程泄漏:确保线程池正确关闭,任务处理异常。
七、性能调优建议
合理设置线程池大小:
CPU密集型:
线程数 = CPU核心数 + 1IO密集型:
线程数 = CPU核心数 * (1 + 平均等待时间/计算时间)
减少锁竞争:使用分段锁、无锁数据结构(如
Disruptor框架)。监控工具:使用JConsole、VisualVM分析线程状态,检测死锁。
示例:生产者-消费者模型
java
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);
// 生产者
new Thread(() -> {
while (true) {
int num = produceItem();
queue.put(num); // 阻塞直到队列有空位
}
}).start();
// 消费者
new Thread(() -> {
while (true) {
int num = queue.take(); // 阻塞直到队列有元素
consumeItem(num);
}
}).start();掌握这些核心概念和工具,能够有效开发高效、健壮的Java多线程应用。实际开发中需结合具体场景选择合适的并发策略,并通过测试确保线程安全与性能达标。