Java案例如何实现线程等待?

wen java案例 10

本文目录导读:

Java案例如何实现线程等待?

  1. 使用 Thread.sleep() - 最简单的等待
  2. 使用 wait() 和 notify() - 对象级别的等待
  3. 使用 CountDownLatch - 多个线程等待一个事件
  4. 使用 CyclicBarrier - 多个线程相互等待
  5. 使用 CompletableFuture - 异步编程中的等待
  6. 使用 LockSupport - 灵活的线程阻塞
  7. 使用 Phaser - 分阶段同步
  8. 最佳实践建议

在Java中实现线程等待主要有以下几种方式,我将通过具体案例来说明:

使用 Thread.sleep() - 最简单的等待

public class SleepExample {
    public static void main(String[] args) {
        System.out.println("开始执行");
        try {
            // 线程暂停3秒
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("3秒后继续执行");
    }
}

使用 wait() 和 notify() - 对象级别的等待

public class WaitNotifyExample {
    private static final Object lock = new Object();
    private static boolean condition = false;
    public static void main(String[] args) {
        // 等待线程
        Thread waiter = new Thread(() -> {
            synchronized (lock) {
                System.out.println("等待线程: 开始等待条件...");
                try {
                    while (!condition) {
                        lock.wait();  // 释放锁并等待
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("等待线程: 条件满足,继续执行");
            }
        });
        // 通知线程
        Thread notifier = new Thread(() -> {
            synchronized (lock) {
                System.out.println("通知线程: 准备设置条件并通知");
                try {
                    Thread.sleep(2000); // 模拟一些工作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                condition = true;
                lock.notify();  // 唤醒等待线程
                System.out.println("通知线程: 已发送通知");
            }
        });
        waiter.start();
        notifier.start();
    }
}

使用 CountDownLatch - 多个线程等待一个事件

import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        // 创建3个工作线程
        for (int i = 1; i <= 3; i++) {
            final int workerId = i;
            new Thread(() -> {
                System.out.println("工作线程 " + workerId + " 开始工作");
                try {
                    Thread.sleep((long) (Math.random() * 3000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("工作线程 " + workerId + " 完成工作");
                latch.countDown(); // 计数器减1
            }).start();
        }
        System.out.println("主线程等待所有工作线程完成");
        latch.await(); // 主线程等待,直到计数器变为0
        System.out.println("所有工作线程完成,主线程继续执行");
    }
}

使用 CyclicBarrier - 多个线程相互等待

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
    public static void main(String[] args) {
        int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
            System.out.println("所有线程都到达屏障点,执行汇总操作");
        });
        for (int i = 1; i <= threadCount; i++) {
            final int threadId = i;
            new Thread(() -> {
                try {
                    System.out.println("线程 " + threadId + " 执行阶段1");
                    Thread.sleep((long) (Math.random() * 2000));
                    System.out.println("线程 " + threadId + " 到达屏障点,等待其他线程");
                    barrier.await(); // 等待所有线程到达
                    System.out.println("线程 " + threadId + " 继续执行阶段2");
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

使用 CompletableFuture - 异步编程中的等待

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("开始异步任务");
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "异步任务结果";
        });
        // 等待异步任务完成
        String result = future.get();
        System.out.println("获取到结果: " + result);
        // 或者使用回调方式,不阻塞主线程
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "另一个异步任务";
        });
        future2.thenAccept(System.out::println);
        System.out.println("主线程继续执行,不会被阻塞");
        // 等待所有任务完成
        Thread.sleep(3000);
    }
}

使用 LockSupport - 灵活的线程阻塞

import java.util.concurrent.locks.LockSupport;
public class LockSupportExample {
    public static void main(String[] args) {
        Thread waitingThread = new Thread(() -> {
            System.out.println("等待线程: 准备阻塞");
            LockSupport.park(); // 阻塞当前线程
            System.out.println("等待线程: 被唤醒,继续执行");
            // 可以配合中断使用
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("等待线程: 被中断");
            }
        });
        Thread unparkThread = new Thread(() -> {
            System.out.println("唤醒线程: 准备唤醒");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            LockSupport.unpark(waitingThread); // 唤醒指定线程
            System.out.println("唤醒线程: 已发送唤醒信号");
        });
        waitingThread.start();
        unparkThread.start();
    }
}

使用 Phaser - 分阶段同步

import java.util.concurrent.Phaser;
public class PhaserExample {
    public static void main(String[] args) {
        Phaser phaser = new Phaser(3) { // 3个参与者
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                System.out.println("阶段 " + phase + " 完成,当前注册者: " + registeredParties);
                return registeredParties == 0; // 返回true表示终止
            }
        };
        for (int i = 1; i <= 3; i++) {
            final int threadId = i;
            new Thread(() -> {
                System.out.println("线程 " + threadId + " 开始阶段1");
                phaser.arriveAndAwaitAdvance(); // 等待所有线程完成阶段1
                System.out.println("线程 " + threadId + " 开始阶段2");
                phaser.arriveAndAwaitAdvance(); // 等待所有线程完成阶段2
                System.out.println("线程 " + threadId + " 结束");
            }).start();
        }
    }
}

最佳实践建议

  1. 选择合适的方式

    • 简单延时使用 Thread.sleep()
    • 线程间协作使用 wait()/notify()
    • 多线程等待一个事件使用 CountDownLatch
    • 多线程相互等待使用 CyclicBarrierPhaser
    • 异步编程使用 CompletableFuture
    • 灵活控制使用 LockSupport
  2. 注意事项

    • 始终处理 InterruptedException
    • wait() 中使用 while 循环检查条件
    • 避免在持有锁时调用 Thread.sleep()
    • 优先使用 java.util.concurrent 包中的工具类

这些案例覆盖了Java中主要的线程等待实现方式,你可以根据具体需求选择最合适的方法。

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