多线程下 wait、notify、park、unpark 和 await、signal 的区别

【悲观锁】Java 线程八锁

【线程】Java线程状态的转换

【悲观锁】Synchronized和ReentrantLock的区别

【线程方法】多线程下 wait、notify、park、unpark 和 await、signal 的区别

【内存】Java中的volatile

【设计模式-单例模式】Java 单例模式双重校验锁变量

【CAS-乐观锁】AtomicInteger

【乐观锁】AtomicReference

【设计模式-享元模式】Java 享元模式自定义连接池

【线程池】自定义线程池

【线程池】ThreadPoolExecutor 线程池

【线程池】Executeror 构建线程池的方法

【线程池】ThreadPoolExecutor 的拒绝策略

【悲观锁】主要的 AQS 方法

【悲观锁】ReentrantReadWriteLock

【同步工具】StampedLock

【同步工具】CountDownLatch

【同步工具】CyclicBarrier和CountDownLatch的区别

线程安全集合类

LinkedBlockingQueue 怎么实现的线程安全

1、所属类和包:

  • waitnotify 属于 Object 类,用于基本的对象监视器机制,而且它们必须在同步块或同步方法中使用。
  • parkunpark 属于 sun.misc.Unsafe 类,提供了更底层的线程挂起和恢复操作。它们可以在任何地方使用,不需要在同步块中。
  • awaitsignal 属于 java.util.concurrent.locks.Condition 接口,通常在 ReentrantLock 的锁保护下使用。它们提供了更高级别的、更灵活的线程协作机制。

2、唤醒方式:

  • notify 只能唤醒等待在同一对象监视器上的一个线程。(调用notify方法而没有任何等待的线程会引发IllegalMonitorStateException异常)
  • notifyAll 唤醒等待在同一对象监视器上的所有线程。(调用 notifyAll方法而没有任何等待的线程是不会引发异常的)
  • unpark 可以指定唤醒哪个线程,因为需要传递线程对象作为参数。(当无park时执行unpark 不会异常,可以先执行unpark再执行park)
  • signal 只能唤醒等待在相同 Condition 对象上的一个线程(signal 唤醒等待在相同 Condition 对象上的所有线程)。
  • awaitsignal 可以通过使用多个 Condition 对象来实现更灵活的唤醒策略。

3、用法示例:

wait 和 notify:

synchronized (lock) {
    while (conditionIsNotMet()) {
        lock.wait();
    }
    // 执行满足条件时的操作
    lock.notify();
}

park 和 unpark:

import java.util.concurrent.locks.LockSupport;

public class ParkUnparkExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " - Before park");
            // 调用park,线程将被阻塞
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + " - After park");
        });

        // 启动线程
        thread.start();

        try {
            Thread.sleep(2000); // 主线程等待一段时间
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName() + " - Before unpark");
        // 调用unpark,唤醒指定线程
        LockSupport.unpark(thread);
        System.out.println(Thread.currentThread().getName() + " - After unpark");
    }
}

await 和 signal:

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

public class AwaitSignalExample {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private boolean conditionMet = false;

    public void waitForCondition() throws InterruptedException {
        lock.lock();
        try {
            while (!conditionMet) {
                System.out.println(Thread.currentThread().getName() + " - Waiting for condition");
                condition.await();
            }
        
            System.out.println(Thread.currentThread().getName() + " - Condition is met");
        } finally {
            lock.unlock();
        }
    }

    public void signalCondition() {
        lock.lock();
        try {
       
            System.out.println(Thread.currentThread().getName() + " - Signaling condition");
            conditionMet = true;
            condition.signal(); 
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        AwaitSignalExample example = new AwaitSignalExample();

        Thread waitingThread = new Thread(() -> {
            try {
                example.waitForCondition();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "WaitingThread");

        Thread signalingThread = new Thread(example::signalCondition, "SignalingThread");

        waitingThread.start();

        
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        signalingThread.start();
    }
}

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值