江明涛的博客
notifyAll 的嵌套使用
notifyAll 的嵌套使用

notifyAll 的嵌套使用

在多线程编程中,notifyAll() 是一个非常重要的方法,它用于唤醒所有当前对象上等待的线程。但是,notifyAll() 的使用也可以进一步嵌套,以实现更复杂的线程同步和通信。
假设我们有一个场景,有多个线程在等待某个共享资源的变化或条件满足时执行特定的任务。这时,我们可以使用 notifyAll() 方法,唤醒所有等待的线程,但这些线程可能还需要等待其他条件满足。这时,嵌套使用 notifyAll() 就能很好地解决这个问题。
下面我们通过一个简单的示例来演示 notifyAll() 的嵌套使用。
假设我们有一个任务管理器 TaskManager,它管理着多个任务。这些任务有不同的状态,比如待执行、执行中和已完成。当有空闲的线程时,TaskManager 就会从待执行的任务列表中选择一个任务执行。如果所有的任务都已完成,那么线程将等待新的任务加入。
首先,我们定义一个 Task 类,表示一个具体的任务,如下所示:
```java
class Task {
    private String name;
    private boolean completed;
    public Task(String name) {
        this.name = name;
        completed = false;
    }
    public synchronized void complete() {
        completed = true;
        notifyAll(); // 通知所有等待该任务完成的线程
    }
    public synchronized void waitForCompletion() throws InterruptedException {
        while (!completed) {
            wait(); // 等待任务完成
        }
    }
}
```
接下来,我们定义 TaskManager 类,负责管理任务的执行和等待,如下所示:
```java
class TaskManager {
    private List tasks;
    public TaskManager() {
        tasks = new ArrayList<>();
    }
    public synchronized void addTask(Task task) {
        tasks.add(task);
        notifyAll(); // 通知所有等待任务的线程
    }
    public synchronized Task getPendingTask() throws InterruptedException {
        while (tasks.isEmpty()) {
            wait(); // 等待新任务加入
        }
        Task task = tasks.remove(0);
        return task;
    }
}
```
现在,我们可以创建多个线程来执行任务。每个线程都是一个 TaskExecutor,它从 TaskManager 中取出待执行的任务并执行。当所有任务都完成时,线程将等待新任务的加入。
```java
class TaskExecutor implements Runnable {
    private TaskManager taskManager;
    public TaskExecutor(TaskManager taskManager) {
        this.taskManager = taskManager;
    }
    @Override
    public void run() {
        try {
            while (true) {
                Task task = taskManager.getPendingTask();
                System.out.println("开始执行任务:" + task.getName());
                Thread.sleep(1000); // 模拟任务的执行
                task.complete(); // 任务执行完成
                System.out.println("任务完成:" + task.getName());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
```
最后,我们可以在主线程中创建 TaskManager 和多个 TaskExecutor,模拟任务的调度和执行。
```java
public class Main {
    public static void main(String[] args) {
        TaskManager taskManager = new TaskManager();
        for (int i = 0; i < 5; i++) {
            new Thread(new TaskExecutor(taskManager)).start();
        }
        // 创建一些任务并添加到 TaskManager 中
        for (int i = 0; i < 10; i++) {
            Task task = new Task("Task " + i);
            taskManager.addTask(task);
            try {
                Thread.sleep(500); // 模拟任务的加入
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
```
在上面的示例中,TaskManager 使用 notifyAll() 方法通知所有等待任务的线程,而 Task 类中使用 notifyAll() 方法通知所有等待该任务完成的线程。这样,我们就实现了 notifyAll() 的嵌套使用,可以更精确地控制线程的同步和通信。
总结起来,notifyAll() 的嵌套使用可以帮助我们更灵活地实现多线程编程中的同步和通信。通过合理地设计和组织线程间的等待和唤醒,我们能够更高效地利用系统资源,提升程序的执行效率。