行业资讯 2025年08月6日
0 收藏 0 点赞 109 浏览 4576 个字
摘要 :

文章目录 Condition接口 Condition实现等待/通知机制 多个Condition实例实现等待/通知机制  总结 synchronized关键字与wait()和notify/notifyAll()方法相结合可以实现……




  • Condition接口
  • Condition实现等待/通知机制
  • 多个Condition实例实现等待/通知机制
  •  总结

synchronized关键字与wait()和notify/notifyAll()方法相结合可以实现等待/通知机制,之前我们讲过《Java多线程:线程间通信(等待/通知机制)》,ReentrantLock类也可以借助于Condition接口与newCondition()方法。

synchronized关键字在使用notify/notifyAll()方法进行通知时,被通知的线程是由JVM选择的,使用ReentrantLock类结合Condition实例可以实现“选择性通知”。

synchronized关键字就相当于整个Lock对象中只有一个Condition实例,所有的线程都注册在该一个实例上。

如果执行notifyAll()方法的话就会通知所有处于等待状态的线程,这样会造成很大的效率问题,而Condition可以实现多路通知功能也就是在一个Lock对象中可以创建多个Condition实例(即对象监视器),线程对象可以注册在指定的Condition中,Condition实例的signalAll()方法 只会唤醒注册在该Condition实例中的所有等待线程。从而可以有选择性的进行线程通知,在调度线程上更加灵活。

Condition接口

    //使当前线程在接到信号或被中断之前一直处于等待状态。
    void await();
 
    //使当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
    boolean await(long time, TimeUnit unit);
 
    //使当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
    long awaitNanos(long nanosTimeout);
 
    //使当前线程在接到信号之前一直处于等待状态。
    void awaitUninterruptibly();
 
    //使当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。
    boolean awaitUntil(Date deadline);
 
    //唤醒一个等待线程。
    void signal();
 
    //唤醒所有等待线程。
    void signalAll();

Condition实现等待/通知机制

当调用 await() 语句后,线程将被阻塞,必须执行完signal()所在的try语句块之后才释放锁,condition.await()后的语句才能被执行。

package ReentrantLockTest;
 
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
public class Test {
 
    public static void main(String[] args) throws InterruptedException {
        MyService service = new MyService();
 
        MyThread a = new MyThread(service);
        a.start();
 
        Thread.sleep(3000);
 
        service.signal();
    }
 
    static public class MyService {
 
        private Lock lock = new ReentrantLock();
 
        public Condition condition = lock.newCondition();
 
        public void await() {
            lock.lock();
            try {
                System.out.println(\"准备调用condition.await()方法,将该线程阻塞\");
                condition.await();
                System.out.println(\"已调用condition.await()方法,此时已被 signal() 方法唤醒\");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
 
        public void signal() {
            lock.lock();
            try {
                System.out.println(\"准备调用condition.signal()方法\");
                condition.signal();
                Thread.sleep(3000);
                System.out.println(\"已调用condition.signal()方法,去唤醒 await() 方法\");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
 
 
    static public class MyThread extends Thread {
        private MyService service;
 
        public MyThread(MyService service) {
            this.service = service;
        }
 
        @Override
        public void run() {
            service.await();
        }
    }
 
}

输出如下:

准备调用condition.await()方法,将该程序阻塞
准备调用condition.signal()方法
已调用condition.signal()方法,去唤醒 await() 方法
已调用condition.await()方法,此时已被 signal() 方法唤醒

多个Condition实例实现等待/通知机制

一个Lock对象中可以创建多个Condition实例,调用某个实例的signalAll()方法 只会唤醒注册在该Condition实例中的所有等待线程。

package ReentrantLockTest;
 
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
public class LockTest {
 
    private Lock lock = new ReentrantLock();
 
    private Condition conditionA = lock.newCondition();
 
    private Condition conditionB = lock.newCondition();
 
    public void awaitA() {
        lock.lock();
        try {
            System.out.println(\"准备调用conditionA.await()方法,将该线程阻塞\");
            conditionA.await();
            System.out.println(\" awaitA 已被唤醒\");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
 
    public void awaitB() {
        lock.lock();
        try {
            System.out.println(\"准备调用conditionB.await()方法,将该线程阻塞\");
            conditionB.await();
            System.out.println(\" awaitB 已被唤醒\");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
 
    public void signalA() {
        lock.lock();
        try {
            System.out.println(\"准备唤醒 conditionA 下的所有线程\");
            conditionA.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
 
    public void signalB() {
        lock.lock();
        try {
            System.out.println(\"准备唤醒 conditionB 下的所有线程\");
            conditionB.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
 
}
package ReentrantLockTest;
 
public class Test {
 
    public static void main(String[] args) throws InterruptedException {
 
        LockTest lockTest = new LockTest();
 
        ThreadA a = new ThreadA(lockTest);
        a.setName(\"A\");
        a.start();
 
        ThreadB b = new ThreadB(lockTest);
        b.setName(\"B\");
        b.start();
 
        Thread.sleep(3000);
 
        lockTest.signalA();
 
    }
 
    static public class ThreadA extends Thread {
 
        private LockTest lockTest;
 
        public ThreadA(LockTest lockTest) {
            this.lockTest = lockTest;
        }
 
        @Override
        public void run() {
            lockTest.awaitA();
        }
    }
 
    static public class ThreadB extends Thread {
 
        private LockTest lockTest;
 
        public ThreadB(LockTest lockTest) {
            this.lockTest = lockTest;
        }
 
        @Override
        public void run() {
            lockTest.awaitB();
        }
    }
}

程序输出:

准备调用conditionA.await()方法,将该线程阻塞
准备调用conditionB.await()方法,将该线程阻塞
准备唤醒 conditionA 下的所有线程
 awaitA 已被唤醒

 总结

在Condition中,用await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll(),传统线程的通信方式,Condition都可以实现,这里注意,Condition是被绑定到Lock上的,要创建一个Lock的Condition必须用newCondition()方法。Condition的强大之处在于,对于一个锁,我们可以为多个线程间建立不同的Condition。

如果采用Object类中的wait(), notify(), notifyAll()实现的话,当写入数据之后需要唤醒读线程时,不可能通过notify()或notifyAll()明确的指定唤醒读线程,而只能通过notifyAll唤醒所有线程,但是notifyAll无法区分唤醒的线程是读线程,还是写线程。所以,通过Condition能够更加精细的控制多线程的休眠与唤醒。

以上就是Java Lock锁Condition接口和newCondition()方法的详解。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/9705.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号