本文目录导读:

我来为你提供几个Java线程同步的典型案例,涵盖不同层次和场景:
基础同步 - synchronized关键字
案例:银行账户并发存取
public class BankAccount {
private double balance;
public BankAccount(double initialBalance) {
this.balance = initialBalance;
}
// 同步方法
public synchronized void deposit(double amount) {
balance += amount;
System.out.println(Thread.currentThread().getName() +
" 存入: " + amount + ", 余额: " + balance);
}
public synchronized boolean withdraw(double amount) {
if (balance >= amount) {
balance -= amount;
System.out.println(Thread.currentThread().getName() +
" 取出: " + amount + ", 余额: " + balance);
return true;
}
System.out.println(Thread.currentThread().getName() +
" 取款失败,余额不足!");
return false;
}
public synchronized double getBalance() {
return balance;
}
}
// 测试代码
public class BankDemo {
public static void main(String[] args) throws InterruptedException {
BankAccount account = new BankAccount(1000);
// 多个线程同时操作账户
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
account.deposit(200);
try { Thread.sleep(10); } catch (InterruptedException e) {}
}
}, "线程1");
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
account.withdraw(100);
try { Thread.sleep(10); } catch (InterruptedException e) {}
}
}, "线程2");
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("最终余额: " + account.getBalance());
}
}
Lock接口实现
案例:可重入锁与条件变量
import java.util.concurrent.locks.*;
import java.util.ArrayList;
import java.util.List;
public class BoundedBuffer<T> {
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private final List<T> items = new ArrayList<>();
private final int capacity;
public BoundedBuffer(int capacity) {
this.capacity = capacity;
}
public void put(T item) throws InterruptedException {
lock.lock();
try {
while (items.size() >= capacity) {
System.out.println(Thread.currentThread().getName() + " 缓冲区已满,等待消费...");
notFull.await();
}
items.add(item);
System.out.println(Thread.currentThread().getName() + " 生产: " + item +
",现有" + items.size() + "个");
notEmpty.signal();
} finally {
lock.unlock();
}
}
public T take() throws InterruptedException {
lock.lock();
try {
while (items.isEmpty()) {
System.out.println(Thread.currentThread().getName() + " 缓冲区为空,等待生产...");
notEmpty.await();
}
T item = items.remove(0);
System.out.println(Thread.currentThread().getName() + " 消费: " + item +
",剩余" + items.size() + "个");
notFull.signal();
return item;
} finally {
lock.unlock();
}
}
}
// 生产者消费者测试
public class ProducerConsumerDemo {
public static void main(String[] args) {
BoundedBuffer<Integer> buffer = new BoundedBuffer<>(3);
// 生产者
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
buffer.put(i);
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "生产者");
// 消费者
Thread consumer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
int item = buffer.take();
Thread.sleep(150);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "消费者");
producer.start();
consumer.start();
}
}
并发集合的使用
案例:并发任务统计系统
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ConcurrentTaskSystem {
// 线程安全的计数器
private AtomicInteger completedTasks = new AtomicInteger(0);
// 阻塞队列存储任务结果
private BlockingQueue<String> resultQueue = new ArrayBlockingQueue<>(100);
// 并发Map存储任务状态
private ConcurrentHashMap<String, String> taskStates = new ConcurrentHashMap<>();
public void processTasks() throws InterruptedException {
// 线程池执行任务
ExecutorService executor = Executors.newFixedThreadPool(5);
// 提交任务
for (int i = 0; i < 20; i++) {
int taskId = i;
executor.submit(() -> {
String taskName = "Task-" + taskId;
// 更新任务状态
taskStates.put(taskName, "RUNNING");
try {
Thread.sleep((long)(Math.random() * 1000));
// 模拟成功或失败
if (Math.random() > 0.3) {
String result = "任务 " + taskName + " 完成,耗时 " +
(long)(Math.random() * 500) + "ms";
resultQueue.put(result);
int completed = completedTasks.incrementAndGet();
taskStates.put(taskName, "SUCCESS");
synchronized(this) {
System.out.printf("已完成 %d 个任务,成功率: %.1f%%%n",
completed, (completed / 20.0) * 100);
}
} else {
taskStates.put(taskName, "FAILED");
System.out.println("任务 " + taskName + " 执行失败");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 关闭线程池
executor.shutdown();
// 等待所有任务完成
executor.awaitTermination(10, TimeUnit.SECONDS);
// 输出最终统计
System.out.println("\n===== 任务统计 =====");
System.out.println("总任务数: 20");
System.out.println("完成任务: " + completedTasks.get());
System.out.println("任务状态分布: ");
taskStates.forEach((task, state) ->
System.out.printf(" %s: %s%n", task, state));
// 从队列中取出部分结果
System.out.println("\n===== 任务结果(前5个) =====");
for (int i = 0; i < 5 && !resultQueue.isEmpty(); i++) {
System.out.println(resultQueue.poll());
}
}
public static void main(String[] args) throws InterruptedException {
new ConcurrentTaskSystem().processTasks();
}
}
死锁演示与解决
案例:哲学家就餐问题
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class DiningPhilosophers {
static class Chopstick {
private final String name;
private final ReentrantLock lock = new ReentrantLock();
public Chopstick(String name) {
this.name = name;
}
public boolean tryPickUp() {
try {
// 尝试获取筷子,超时则放弃
return lock.tryLock(100, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
public void putDown() {
lock.unlock();
}
public String getName() {
return name;
}
}
static class Philosopher implements Runnable {
private final String name;
private final Chopstick left;
private final Chopstick right;
private int eatCount = 0;
public Philosopher(String name, Chopstick left, Chopstick right) {
this.name = name;
this.left = left;
this.right = right;
}
@Override
public void run() {
try {
while (eatCount < 5) {
// 思考
think();
// 尝试获取两只筷子
if (left.tryPickUp()) {
System.out.println(name + " 拿到了左手的筷子" + left.getName());
if (right.tryPickUp()) {
System.out.println(name + " 拿到了右手的筷子" + right.getName());
// 吃饭
eat();
right.putDown();
left.putDown();
System.out.println(name + " 放下了筷子");
} else {
// 拿不到右手的筷子,放下左手的
left.putDown();
System.out.println(name + " 放弃了左手的筷子");
}
}
}
System.out.println(name + " 已经吃饱了,吃了" + eatCount + "次");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void think() throws InterruptedException {
System.out.println(name + " 正在思考...");
Thread.sleep((long)(Math.random() * 500));
}
private void eat() throws InterruptedException {
eatCount++;
System.out.println(name + " 正在吃饭,吃了第" + eatCount + "次");
Thread.sleep((long)(Math.random() * 300));
}
}
public static void main(String[] args) {
Chopstick[] chopsticks = new Chopstick[5];
for (int i = 0; i < 5; i++) {
chopsticks[i] = new Chopstick("筷子" + (i + 1));
}
String[] names = {"哲学家A", "哲学家B", "哲学家C", "哲学家D", "哲学家E"};
for (int i = 0; i < 5; i++) {
Chopstick left = chopsticks[i];
Chopstick right = chopsticks[(i + 1) % 5];
Thread philosopher = new Thread(
new Philosopher(names[i], left, right), names[i]);
philosopher.start();
}
}
}
高级同步 - ReadWriteLock
案例:共享数据缓存
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.HashMap;
import java.util.Map;
public class CacheSystem {
private final Map<String, Object> cache = new HashMap<>();
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
// 读操作 - 可并发
public Object read(String key) {
rwLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 正在读取 " + key);
Thread.sleep(100); // 模拟读取耗时
Object value = cache.get(key);
System.out.println(Thread.currentThread().getName() + " 读取完成: " + value);
return value;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
} finally {
rwLock.readLock().unlock();
}
}
// 写操作 - 独占
public void write(String key, Object value) {
rwLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 正在写入 " + key + "=" + value);
Thread.sleep(100); // 模拟写入耗时
cache.put(key, value);
System.out.println(Thread.currentThread().getName() + " 写入完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
rwLock.writeLock().unlock();
}
}
public static void main(String[] args) throws InterruptedException {
CacheSystem cache = new CacheSystem();
cache.write("initial", "data");
// 多个读取线程
for (int i = 0; i < 3; i++) {
new Thread(() -> {
for (int j = 0; j < 3; j++) {
cache.read("initial");
}
}, "Reader-" + i).start();
}
// 一个写入线程
new Thread(() -> {
for (int j = 0; j < 3; j++) {
cache.write("key-" + j, "value-" + j);
}
}, "Writer").start();
}
}
这些案例涵盖了:
- synchronized - 最基础的同步方式
- Lock与Condition - 更灵活的锁控制
- 并发集合 - 线程安全的数据结构
- 死锁处理 - 使用超时避免死锁
- ReadWriteLock - 读写分离优化性能
选择建议:
- 简单场景用
synchronized - 需要超时控制或条件变量用
Lock - 读多写少用
ReadWriteLock - 并发数据结构直接使用
java.util.concurrent包
注意:实际开发中还要考虑锁粒度、性能影响和死锁风险。