JUC--Condition简介和使用

本文通过示例介绍了Java中Condition机制的基本用法,包括如何使用Condition实现线程间的等待和唤醒,对比了Condition与Object的wait和notify方法的区别。

1 概述

我们知道针对synchronized关键字实现的加锁操作操作我们可以使用wait和notify来实现线程的等待和唤醒线程,但是我们清楚这个时候就只能有一个线程进入等待,那么如果我们想要多个线程等待,同时我们可以唤醒多个线程怎么办呢?这个时候就需要用到Lock对应的Condition来完成了。

我们知道针对Lock与synchronized的区别在于,Lock的操作更加灵活,并且可以响应超时等待和中断。我们下面就来看一看Contidion具体是如何使用的。

2 示例

/**
 * 演示Condition的使用
 * @author: LIUTAO
 * @Date: Created in 2018/9/3  10:12
 * @Modified By:
 */
public class ConditionDemo {
    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        Condition condition = reentrantLock.newCondition();

        new Thread(() -> {
            reentrantLock.lock();
            System.out.println(Thread.currentThread().getName()+"get lock successfully");
            System.out.println(Thread.currentThread().getName()+"waiting signal");
            try {
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" get signal successfully");
            reentrantLock.unlock();

        },"first thread ").start();

        new Thread(() -> {
            reentrantLock.lock();
            System.out.println(Thread.currentThread().getName()+"get lock successfully");

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

            System.out.println(Thread.currentThread().getName()+"send signal");
            condition.signalAll();
            System.out.println(Thread.currentThread().getName()+" get signal successfully");
            reentrantLock.unlock();

        },"second thread ").start();
    }
}

运行上面的代码,我们可以看见如下输出:

first thread get lock successfully
first thread waiting signal
second thread get lock successfully
second thread send signal
second thread  get signal successfully
first thread  get signal successfully

我们可以看出在first thread调用了condition.await()后,first thread让出了锁,然后second thread 获取到锁。而当second thread调用condition.signalAll()的时候又让出了锁,first thread获取到锁。这就实现了线程的等待和唤醒。

我们需要注意的是Condition的使用必须在lock()和unlock()方法之间。

3 函数说明

这里我们针对Condition具有的函数进行一个简单的介绍。

await():使当前线程等待,同时释放当前锁,当其他线程中使用signal()时或者signalAll()方法时,线程会重新获得锁并继续执行。或者当线程被中断时,也能跳出等待。该方法和Object的wait()类似。

awaitUninterruptibly():该方法和await()相同,但是不响应中断。

await(long time, TimeUnit unit):当前线程等待,直到线程被唤醒或者中断,或者等待时间耗尽,这里第二个参数就是等待时间单位。

awaitNanos(long nanosTimeout):当前线程等待,直到线程被唤醒或者中断,或者等待时间耗尽,等待的时间单位是固定的为纳秒(十亿分之一秒)。

awaitUntil(Date deadline):前线程等待,直到线程被唤醒或者中断,或者到达具体的截至日期。

signal():唤醒一个等待的线程。

signalAll():唤醒所有等待的线程。

4 和Object的wait()与notify()的区别

(1)Object的一个对象只能又一个等待队列,而针对Lock,一个对象可以有多个等待等待队列。

(2)使用Lock比使用Object加锁的方式具有更好的灵活性。可以响应中断和设置获取锁的超时间。

(3)Lock支持公平性和非公平性的设置,而synchronized不支持。

以上就是针对Condition使用的详解,下面的文章我们将继续学习Condition源码的实现。

在C++中,虽然没有直接对应Java的 **IOC**(控制反转) **JUC**(Java Util Concurrent) 的库或框架,但可以通过标准库(如 `<memory>`、`<functional>`、`<thread>` `<future>`)以及第三方库(如 Boost、Google Guice 的 C++ 版本)来实现类似的功能。 ### 控制反转(IOC)在 C++ 中的实现 C++ 中的控制反转通常通过 **依赖注入**(Dependency Injection) 或 **模板方法模式** 来实现,而不是像 Spring 那样的完整 IOC 容器。标准库中的 `std::function` `std::bind` 可用于实现轻量级的回调机制,从而模拟 IOC 的行为。 ```cpp #include <iostream> #include <functional> class Service { public: void doSomething() { std::cout << "Service is doing something." << std::endl; } }; class Client { public: using ServiceFactory = std::function<Service*()>; Client(ServiceFactory factory) : service(factory()) {} void perform() { service->doSomething(); } private: Service* service; }; int main() { Client::ServiceFactory factory = []() { return new Service(); }; Client client(factory); client.perform(); return 0; } ``` 上述代码通过工厂函数注入依赖,实现了控制反转的基本思想,即由外部决定依赖对象的创建方式 [^2]。 ### 并发库(JUC)在 C++ 中的实现 C++11 标准引入了对多线程并发编程的原生支持,定义在 `<thread>`、`<mutex>`、`<condition_variable>` `<future>` 等头文件中。这些功能可以实现类似于 Java JUC 中的线程池、异步任务、锁机制等。 #### 线程管理与异步任务 ```cpp #include <iostream> #include <future> #include <thread> int asyncTask() { std::this_thread::sleep_for(std::chrono::seconds(1)); return 42; } int main() { std::future<int> result = std::async(std::launch::async, asyncTask); std::cout << "Result: " << result.get() << std::endl; // 等待异步任务完成 return 0; } ``` 上述代码使用 `std::async` 创建异步任务,并通过 `std::future` 获取执行结果,这与 Java 中的 `Future` `ExecutorService` 类似 [^2]。 #### 互斥锁与条件变量 ```cpp #include <iostream> #include <thread> #include <mutex> #include <condition_variable> std::mutex mtx; std::condition_variable cv; bool ready = false; void wait_for_ready() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{ return ready; }); std::cout << "Ready!" << std::endl; } void set_ready() { std::this_thread::sleep_for(std::chrono::seconds(1)); { std::lock_guard<std::mutex> lock(mtx); ready = true; } cv.notify_all(); } int main() { std::thread t1(wait_for_ready); std::thread t2(set_ready); t1.join(); t2.join(); return 0; } ``` 该示例使用 `std::mutex` `std::condition_variable` 实现线程同步,与 Java 中的 `ReentrantLock` `Condition` 类似 [^2]。 ### 总结 C++ 虽然没有 Java 那样成熟的 IOC 容器(如 Spring) JUC(Java Util Concurrent)库,但通过标准库提供的函数对象、线程、锁异步机制,可以实现类似的功能。开发者可以结合模板、函数指针、lambda 表达式等特性,构建灵活的依赖管理并发控制机制。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值