Java多线程编程实战:从基础到并发工具包应用 | Java并发编程指南

2025-08-24 0 691

深入理解Java多线程编程,掌握线程安全、同步机制和并发工具包的使用

多线程编程简介

在现代计算环境中,多线程编程是提高应用程序性能和响应能力的关键技术。Java从最初版本就提供了多线程支持,并在后续版本中不断增强了并发编程能力。

多线程允许程序同时执行多个任务,充分利用多核处理器的计算能力。然而,多线程编程也带来了复杂性,如线程安全、死锁和资源竞争等问题,需要开发者特别注意。

线程创建与管理

Java提供了两种创建线程的方式:继承Thread类和实现Runnable接口。

继承Thread类

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程运行中: " + Thread.currentThread().getName());
    }
}

// 使用方式
MyThread thread = new MyThread();
thread.start();

实现Runnable接口

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程运行中: " + Thread.currentThread().getName());
    }
}

// 使用方式
Thread thread = new Thread(new MyRunnable());
thread.start();

使用Lambda表达式(Java 8+)

Thread thread = new Thread(() -> {
    System.out.println("使用Lambda创建的线程: " + Thread.currentThread().getName());
});
thread.start();

线程基本控制

Thread thread = new Thread(() -> {
    // 线程任务
});

thread.start();    // 启动线程
thread.join();     // 等待线程结束
thread.interrupt(); // 中断线程

// 获取当前线程
Thread currentThread = Thread.currentThread();
System.out.println("当前线程: " + currentThread.getName());

线程同步机制

当多个线程访问共享资源时,需要同步机制来确保数据一致性。

synchronized关键字

class Counter {
    private int count = 0;
    
    // 同步方法
    public synchronized void increment() {
        count++;
    }
    
    // 同步代码块
    public void decrement() {
        synchronized(this) {
            count--;
        }
    }
    
    public synchronized int getCount() {
        return count;
    }
}

ReentrantLock

import java.util.concurrent.locks.ReentrantLock;

class SafeCounter {
    private int count = 0;
    private final ReentrantLock lock = new ReentrantLock();
    
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
    
    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}

volatile关键字

class VolatileExample {
    private volatile boolean flag = false;
    
    public void setFlagTrue() {
        flag = true;
    }
    
    public boolean isFlag() {
        return flag;
    }
}

线程池与执行器框架

Java的Executor框架提供了线程池管理,避免了频繁创建和销毁线程的开销。

创建线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

// 创建固定大小的线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(5);

// 创建缓存线程池
ExecutorService cachedPool = Executors.newCachedThreadPool();

// 创建单线程线程池
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

使用线程池

ExecutorService executor = Executors.newFixedThreadPool(3);

// 提交Runnable任务
executor.submit(() -> {
    System.out.println("任务执行中: " + Thread.currentThread().getName());
});

// 提交Callable任务并获取Future
Future future = executor.submit(() -> {
    Thread.sleep(1000);
    return 42;
});

// 获取任务结果
try {
    Integer result = future.get();
    System.out.println("任务结果: " + result);
} catch (Exception e) {
    e.printStackTrace();
}

// 关闭线程池
executor.shutdown();

并发集合类

Java提供了多种线程安全的集合类,替代需要手动同步的传统集合。

ConcurrentHashMap

import java.util.concurrent.ConcurrentHashMap;

ConcurrentHashMap map = new ConcurrentHashMap();

// 线程安全的操作
map.put("key1", 1);
map.putIfAbsent("key1", 2); // 只有key不存在时才会放入

// 遍历操作也是线程安全的
map.forEach((key, value) -> {
    System.out.println(key + ": " + value);
});

CopyOnWriteArrayList

import java.util.concurrent.CopyOnWriteArrayList;

CopyOnWriteArrayList list = new CopyOnWriteArrayList();

// 添加元素
list.add("item1");
list.add("item2");

// 迭代操作是线程安全的,基于快照机制
for (String item : list) {
    System.out.println(item);
}

BlockingQueue

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

BlockingQueue queue = new ArrayBlockingQueue(10);

// 生产者线程
new Thread(() -> {
    try {
        queue.put("message");
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}).start();

// 消费者线程
new Thread(() -> {
    try {
        String message = queue.take();
        System.out.println("收到消息: " + message);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}).start();

高级并发工具

Java并发包提供了多种高级工具来处理复杂并发场景。

CountDownLatch

import java.util.concurrent.CountDownLatch;

CountDownLatch latch = new CountDownLatch(3);

for (int i = 0; i  {
        System.out.println("子线程执行任务");
        latch.countDown(); // 计数减1
    }).start();
}

latch.await(); // 等待所有子线程完成
System.out.println("所有子线程已完成,主线程继续执行");

CyclicBarrier

import java.util.concurrent.CyclicBarrier;

CyclicBarrier barrier = new CyclicBarrier(3, () -> {
    System.out.println("所有线程已到达屏障点");
});

for (int i = 0; i  {
        try {
            System.out.println("线程到达屏障点");
            barrier.await(); // 等待其他线程
            System.out.println("线程继续执行");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }).start();
}

Semaphore

import java.util.concurrent.Semaphore;

Semaphore semaphore = new Semaphore(3); // 允许3个线程同时访问

for (int i = 0; i  {
        try {
            semaphore.acquire(); // 获取许可
            System.out.println("线程获得许可,执行任务");
            Thread.sleep(1000);
            semaphore.release(); // 释放许可
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }).start();
}

实战案例:生产者-消费者问题

下面通过一个完整的生产者-消费者示例展示多线程编程的实际应用:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ProducerConsumerExample {
    
    public static void main(String[] args) {
        // 创建大小为5的阻塞队列
        BlockingQueue queue = new ArrayBlockingQueue(5);
        
        // 创建生产者
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i  {
            try {
                for (int i = 0; i < 10; i++) {
                    Integer value = queue.take(); // 如果队列空,则阻塞
                    System.out.println("消费者处理: " + value);
                    Thread.sleep(1000); // 模拟处理时间
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        // 启动生产者和消费者
        producer.start();
        consumer.start();
        
        // 等待线程结束
        try {
            producer.join();
            consumer.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        System.out.println("生产消费任务完成");
    }
}

使用线程池优化

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;

public class AdvancedProducerConsumer {
    
    public static void main(String[] args) {
        BlockingQueue queue = new ArrayBlockingQueue(5);
        ExecutorService executor = Executors.newFixedThreadPool(4);
        
        // 创建多个生产者
        for (int i = 0; i  {
                try {
                    for (int j = 0; j < 5; j++) {
                        int value = (int) (Math.random() * 100);
                        queue.put(value);
                        System.out.println(Thread.currentThread().getName() + 
                                         " 生产: " + value);
                        Thread.sleep(300);
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        
        // 创建多个消费者
        for (int i = 0; i  {
                try {
                    for (int j = 0; j < 5; j++) {
                        Integer value = queue.take();
                        System.out.println(Thread.currentThread().getName() + 
                                         " 消费: " + value);
                        Thread.sleep(500);
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        
        executor.shutdown();
        while (!executor.isTerminated()) {
            // 等待所有任务完成
        }
        
        System.out.println("所有生产消费任务完成");
    }
}

最佳实践与常见陷阱

多线程编程需要遵循一些最佳实践来避免常见问题:

1. 避免死锁

// 错误的做法 - 可能导致死锁
public void transfer(Account from, Account to, int amount) {
    synchronized(from) {
        synchronized(to) {
            from.withdraw(amount);
            to.deposit(amount);
        }
    }
}

// 正确的做法 - 使用固定的锁顺序
public void safeTransfer(Account from, Account to, int amount) {
    Object firstLock = from.getId() < to.getId() ? from : to;
    Object secondLock = from.getId() < to.getId() ? to : from;
    
    synchronized(firstLock) {
        synchronized(secondLock) {
            from.withdraw(amount);
            to.deposit(amount);
        }
    }
}

2. 使用线程局部变量

// 使用ThreadLocal维护线程局部变量
private static final ThreadLocal dateFormat =
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

public String formatDate(Date date) {
    return dateFormat.get().format(date); // 每个线程有自己的实例
}

3. 正确处理线程中断

public void run() {
    try {
        while (!Thread.currentThread().isInterrupted()) {
            // 执行任务
            Thread.sleep(1000);
        }
    } catch (InterruptedException e) {
        // 恢复中断状态
        Thread.currentThread().interrupt();
    }
}

4. 避免过度同步

只在必要的时候同步,减少同步块的大小,提高并发性能。

5. 使用并发工具类

优先使用Java并发包中的工具类,而不是自己实现同步机制。

Java多线程编程实战:从基础到并发工具包应用 | Java并发编程指南
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 java Java多线程编程实战:从基础到并发工具包应用 | Java并发编程指南 https://www.taomawang.com/server/java/965.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务