线程等待唤醒机制

线程等待唤醒机制是多线程编程中的重要概念,用于实现线程间的协作和同步。在 Java 里,主要通过 Object 类的 wait()notify()notifyAll() 方法,以及 Lock 接口和 Condition 接口来实现这一机制。以下为你详细介绍这两种实现方式:

使用 Object 类的 wait()notify()notifyAll() 方法

wait()notify()notifyAll()Object 类的方法,任何 Java 对象都可以调用这些方法。不过,这些方法必须在 synchronized 代码块或同步方法中使用。

方法说明

  • wait():使当前线程进入等待状态,同时释放对象的锁,直到其他线程调用该对象的 notify()notifyAll() 方法将其唤醒。
  • notify():随机唤醒在此对象监视器上等待的一个线程。
  • notifyAll():唤醒在此对象监视器上等待的所有线程。

示例代码

class SharedResource {
    private boolean flag = false;

    public synchronized void waitForSignal() throws InterruptedException {
        // 当条件不满足时,线程进入等待状态
        while (!flag) {
            wait();
        }
        System.out.println(Thread.currentThread().getName() + " 被唤醒,继续执行。");
        // 重置标志
        flag = false;
    }

    public synchronized void sendSignal() {
        // 设置标志
        flag = true;
        // 唤醒等待的线程
        notify();
        System.out.println(Thread.currentThread().getName() + " 发送信号,唤醒一个等待的线程。");
    }
}

public class WaitNotifyExample {
    public static void main(String[] args) {
        SharedResource sharedResource = new SharedResource();

        // 创建等待线程
        Thread waitThread = new Thread(() -> {
            try {
                sharedResource.waitForSignal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "WaitThread");

        // 创建通知线程
        Thread notifyThread = new Thread(() -> {
            try {
                // 模拟一些操作
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            sharedResource.sendSignal();
        }, "NotifyThread");

        waitThread.start();
        notifyThread.start();
    }
}

代码解释

  • SharedResource 类包含一个 flag 标志,用于表示是否可以继续执行。
  • waitForSignal() 方法中,当 flagfalse 时,线程调用 wait() 方法进入等待状态,直到 flag 变为 true 且被其他线程唤醒。
  • sendSignal() 方法中,将 flag 设置为 true,并调用 notify() 方法唤醒一个等待的线程。

使用 Lock 接口和 Condition 接口

Lock 接口和 Condition 接口是 Java 并发包中提供的更灵活的锁和条件变量机制,与 Object 类的方法相比,Condition 可以实现更精细的线程控制。

方法说明

  • await():使当前线程进入等待状态,同时释放锁,直到其他线程调用该 Condition 对象的 signal()signalAll() 方法将其唤醒。
  • signal():随机唤醒在该 Condition 对象上等待的一个线程。
  • signalAll():唤醒在该 Condition 对象上等待的所有线程。

示例代码

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class SharedResourceWithLock {
    private boolean flag = false;
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();

    public void waitForSignal() throws InterruptedException {
        lock.lock();
        try {
            // 当条件不满足时,线程进入等待状态
            while (!flag) {
                condition.await();
            }
            System.out.println(Thread.currentThread().getName() + " 被唤醒,继续执行。");
            // 重置标志
            flag = false;
        } finally {
            lock.unlock();
        }
    }

    public void sendSignal() {
        lock.lock();
        try {
            // 设置标志
            flag = true;
            // 唤醒等待的线程
            condition.signal();
            System.out.println(Thread.currentThread().getName() + " 发送信号,唤醒一个等待的线程。");
        } finally {
            lock.unlock();
        }
    }
}

public class LockConditionExample {
    public static void main(String[] args) {
        SharedResourceWithLock sharedResource = new SharedResourceWithLock();

        // 创建等待线程
        Thread waitThread = new Thread(() -> {
            try {
                sharedResource.waitForSignal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "WaitThread");

        // 创建通知线程
        Thread notifyThread = new Thread(() -> {
            try {
                // 模拟一些操作
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            sharedResource.sendSignal();
        }, "NotifyThread");

        waitThread.start();
        notifyThread.start();
    }
}

代码解释

  • SharedResourceWithLock 类使用 ReentrantLock 作为锁,通过 lock.newCondition() 创建一个 Condition 对象。
  • waitForSignal() 方法中,当 flagfalse 时,线程调用 condition.await() 方法进入等待状态,直到 flag 变为 true 且被其他线程唤醒。
  • sendSignal() 方法中,将 flag 设置为 true,并调用 condition.signal() 方法唤醒一个等待的线程。

总结

  • Object 类的方法:简单易用,适用于基本的线程等待唤醒场景,但功能相对有限。
  • Lock 接口和 Condition 接口:提供了更灵活的锁和条件变量机制,可以实现更精细的线程控制,适用于复杂的多线程场景。
JUC编程 文章被收录于专栏

JUC 是 Java.util.concurrent 包的简称,它是 Java 5 引入的一个用于处理并发编程的工具包,为 Java 开发者提供了一系列用于高效处理并发任务的类和接口,极大地简化了多线程编程的复杂性。

全部评论

相关推荐

09-28 22:01
已编辑
广西科技大学 IT技术支持
合适才能收到offe...:找桌面运维?
点赞 评论 收藏
分享
Aurora23:属于挂一半,暂时进池子了,隔一段时间没有其他组捞的话就彻底结束了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务