Java线程同步案例

wen java案例 3

本文目录导读:

Java线程同步案例

  1. 基础同步 - synchronized关键字
  2. Lock接口实现
  3. 并发集合的使用
  4. 死锁演示与解决
  5. 高级同步 - ReadWriteLock

我来为你提供几个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();
    }
}

这些案例涵盖了:

  1. synchronized - 最基础的同步方式
  2. Lock与Condition - 更灵活的锁控制
  3. 并发集合 - 线程安全的数据结构
  4. 死锁处理 - 使用超时避免死锁
  5. ReadWriteLock - 读写分离优化性能

选择建议:

  • 简单场景用synchronized
  • 需要超时控制或条件变量用Lock
  • 读多写少用ReadWriteLock
  • 并发数据结构直接使用java.util.concurrent

注意:实际开发中还要考虑锁粒度、性能影响和死锁风险。

抱歉,评论功能暂时关闭!