Java线程唤醒案例如何操作

wen java案例 20

本文目录导读:

Java线程唤醒案例如何操作

  1. 使用wait/notify机制
  2. 使用ReentrantLock + Condition
  3. 使用Semaphore(信号量)
  4. 使用CountDownLatch
  5. 使用CompletableFuture
  6. 重要注意事项

我来详细讲解Java线程唤醒的几种典型操作案例。

使用wait/notify机制

基础生产者-消费者案例

public class WaitNotifyExample {
    // 共享资源
    private static final Object lock = new Object();
    private static boolean taskCompleted = false;
    public static void main(String[] args) throws InterruptedException {
        // 等待线程
        Thread waiter = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("等待线程开始执行,等待条件满足...");
                    while (!taskCompleted) {
                        lock.wait(); // 释放锁并等待
                    }
                    System.out.println("等待线程被唤醒,条件已满足");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        // 通知线程
        Thread notifier = new Thread(() -> {
            synchronized (lock) {
                try {
                    Thread.sleep(2000); // 模拟工作
                    taskCompleted = true;
                    System.out.println("通知线程完成任务,准备唤醒等待线程");
                    lock.notify(); // 唤醒等待线程
                    System.out.println("通知线程已发送唤醒信号");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        waiter.start();
        Thread.sleep(100); // 确保等待线程先获得锁
        notifier.start();
    }
}

生产者-消费者完整案例

import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumerExample {
    private static final int MAX_SIZE = 5;
    private final Queue<Integer> buffer = new LinkedList<>();
    public static void main(String[] args) {
        ProducerConsumerExample example = new ProducerConsumerExample();
        // 生产者线程
        Thread producer = new Thread(() -> {
            int value = 0;
            while (true) {
                try {
                    synchronized (example) {
                        // 缓冲区满则等待
                        while (example.buffer.size() == MAX_SIZE) {
                            System.out.println("缓冲区已满,生产者等待...");
                            example.wait();
                        }
                        // 生产数据
                        example.buffer.offer(value);
                        System.out.println("生产者生产了: " + value + ",缓冲区大小: " + example.buffer.size());
                        value++;
                        // 唤醒消费者
                        example.notifyAll();
                    }
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        // 消费者线程
        Thread consumer = new Thread(() -> {
            while (true) {
                try {
                    synchronized (example) {
                        // 缓冲区空则等待
                        while (example.buffer.isEmpty()) {
                            System.out.println("缓冲区为空,消费者等待...");
                            example.wait();
                        }
                        // 消费数据
                        int value = example.buffer.poll();
                        System.out.println("消费者消费了: " + value + ",缓冲区大小: " + example.buffer.size());
                        // 唤醒生产者
                        example.notifyAll();
                    }
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        producer.start();
        consumer.start();
    }
}

使用ReentrantLock + Condition

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class LockConditionExample {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private boolean ready = false;
    public static void main(String[] args) throws InterruptedException {
        LockConditionExample example = new LockConditionExample();
        // 等待线程
        Thread waiter = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("等待线程开始执行");
                while (!example.ready) {
                    System.out.println("等待条件满足...");
                    example.condition.await(); // 类似wait()
                }
                System.out.println("等待线程被唤醒,继续执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });
        // 通知线程
        Thread notifier = new Thread(() -> {
            lock.lock();
            try {
                Thread.sleep(2000);
                example.ready = true;
                System.out.println("通知线程设置条件为true");
                example.condition.signal(); // 类似notify()
                System.out.println("通知线程已发送信号");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });
        waiter.start();
        Thread.sleep(100);
        notifier.start();
    }
}

使用Semaphore(信号量)

import java.util.concurrent.Semaphore;
public class SemaphoreExample {
    private final Semaphore semaphore = new Semaphore(0); // 初始许可为0
    public static void main(String[] args) throws InterruptedException {
        SemaphoreExample example = new SemaphoreExample();
        // 等待线程
        Thread waiter = new Thread(() -> {
            try {
                System.out.println("等待线程开始执行");
                example.semaphore.acquire(); // 获取许可,如果没有则阻塞
                System.out.println("等待线程获取到许可,继续执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // 释放线程
        Thread releaser = new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("释放线程准备释放许可");
                example.semaphore.release(); // 释放许可,唤醒等待线程
                System.out.println("释放线程已释放许可");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        waiter.start();
        Thread.sleep(100);
        releaser.start();
    }
}

使用CountDownLatch

import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        // 等待线程
        Thread waiter = new Thread(() -> {
            try {
                System.out.println("等待线程开始执行");
                latch.await(); // 等待计数器归零
                System.out.println("等待线程被唤醒");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // 触发线程
        Thread trigger = new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("触发线程准备唤醒等待线程");
                latch.countDown(); // 计数器减1,当为0时唤醒所有等待线程
                System.out.println("触发线程已完成操作");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        waiter.start();
        Thread.sleep(100);
        trigger.start();
    }
}

使用CompletableFuture

import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
    public static void main(String[] args) throws Exception {
        // 创建一个被阻塞的CompletableFuture
        CompletableFuture<String> future = new CompletableFuture<>();
        // 等待线程
        Thread waiter = new Thread(() -> {
            try {
                System.out.println("等待线程开始执行");
                String result = future.get(); // 阻塞等待结果
                System.out.println("等待线程收到结果: " + result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 完成线程
        Thread completer = new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("完成线程准备完成future");
                future.complete("Hello from completer!");
                System.out.println("完成线程已完成future");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        waiter.start();
        Thread.sleep(100);
        completer.start();
        // 等待完成
        completer.join();
        waiter.join();
    }
}

重要注意事项

  1. 始终在循环中等待:避免虚假唤醒

    while (!condition) {
        wait();
    }
  2. 避免死锁:确保在正确的时机释放锁

  3. 优先使用高级并发工具:如CountDownLatch、CyclicBarrier等

  4. 注意性能:notifyAll比notify更安全,但可能影响性能

  5. 异常处理:InterruptedException需要妥善处理

这些案例涵盖了Java中主要的线程唤醒机制,根据具体场景选择合适的方案。

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