Java多线程Condition接口原理介绍

下面是对于Java多线程Condition接口的原理介绍:

Condition接口是什么?

在Java中,我们可以使用synchronizedwait()notify()notifyAll()等来进行线程同步和通信。而条件对象(Condition)是在Java 5中新增的,它可以更加灵活地控制线程的等待和唤醒,提供了更高级、更安全、更灵活的线程同步方式。

Condition的基本使用

条件对象是与一个锁绑定的,要创建一个条件对象,我们需要先获取锁,然后使用ReentrantLock类的方法newCondition()来创建:

ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();

这样我们就创建了一个条件变量,下一步就可以通过调用conditionawait()方法使得线程进入等待状态,直到调用conditionsignalAll()方法或者signal()方法唤醒线程。

下面是一个简单的示例,两个线程分别执行加和减操作,当结果为零时,主线程输出结果并结束程序。具体的实现过程如下:

public class ConditionDemo {
    private int sum;

    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void add() {
        lock.lock();
        try {
            sum++;
            System.out.println(Thread.currentThread().getName() + " add: " + sum);
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public void sub() {
        lock.lock();
        try {
            while (sum == 0) {
                condition.await();
            }
            sum--;
            System.out.println(Thread.currentThread().getName() + " sub: " + sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ConditionDemo demo = new ConditionDemo();

        Runnable addTask = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    demo.add();
                }
            }
        };

        Runnable subTask = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    demo.sub();
                }
            }
        };

        Thread addThread1 = new Thread(addTask);
        Thread addThread2 = new Thread(addTask);
        Thread subThread = new Thread(subTask);

        addThread1.start();
        addThread2.start();
        subThread.start();

        try {
            addThread1.join();  // 等待线程结束
            addThread2.join();
            subThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Result: " + demo.sum);
    }
}

上述程序中,使用了一个变量sum来保存加减的结果。在加操作中,我们先获取锁,然后将sum增加1,输出结果,并唤醒所有等待condition的线程。在减操作中,我们先获取锁,然后不断判断sum是否为0,如果为0,则调用conditionawait()方法等待;直到被唤醒后,将sum减1,并输出结果。在主线程中,我们启动两个加操作线程和一个减操作线程,等待所有线程运行结束后,输出结果。

使用Condition实现生产者-消费者模式

生产者-消费者模式是大家比较熟悉的一种应用场景。可以使用Condition来实现,示例如下:

public class ProducerConsumerDemo {

    private LinkedList<Integer> buffer = new LinkedList<Integer>();

    private ReentrantLock lock = new ReentrantLock();
    private Condition notEmpty = lock.newCondition();
    private Condition notFull = lock.newCondition();

    public void produce() {
        lock.lock();
        try {
            while (buffer.size() == 10) {
                notFull.await();
            }
            int value = new Random().nextInt(100);
            buffer.addLast(value);
            System.out.println(Thread.currentThread().getName() + " produce " + value);
            notEmpty.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public int consume() {
        lock.lock();
        try {
            while (buffer.size() == 0) {
                notEmpty.await();
            }
            int value = buffer.removeFirst();
            System.out.println(Thread.currentThread().getName() + " consume " + value);
            notFull.signalAll();
            return value;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return -1;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ProducerConsumerDemo demo = new ProducerConsumerDemo();

        Runnable produceTask = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    demo.produce();
                }
            }
        };

        Runnable consumeTask = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    demo.consume();
                }
            }
        };

        Thread producer1 = new Thread(produceTask, "producer1");
        Thread producer2 = new Thread(produceTask, "producer2");
        Thread consumer1 = new Thread(consumeTask, "consumer1");
        Thread consumer2 = new Thread(consumeTask, "consumer2");

        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();

        try {
            producer1.join();
            producer2.join();
            consumer1.join();
            consumer2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在上述示例中,我们使用了一个LinkedList来存储数据。在生产操作中,如果buffer已经满了,那就调用notFull.await()等待;直到有消费者调用了consume()方法,拿走了一些数据,此时有足够的空间存储新的数据,就可以唤醒正在等待的生产者线程。在消费操作中,如果buffer为空,就调用notEmpty.await()等待;直到有生产者调用了produce()方法,放入了一些数据,此时就可以从buffer中取出数据,唤醒正在等待的消费者线程。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程Condition接口原理介绍 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • springboot与springmvc基础入门讲解

    让我来为您详细讲解“springboot与springmvc基础入门讲解”的完整攻略。 简介 Spring Boot是Spring Framework的一个扩展框架,它为Spring开发者提供了更快的开发体验。Spring MVC是一个经典的MVC框架,负责接收HTTP请求并将其转换为相应的处理程序,通常由Controller和Model组成。 本文将对Sp…

    Java 2023年5月15日
    00
  • 一些实用的TAB效果

    一些实用的TAB效果可以通过CSS和JavaScript实现。下面为您提供详细的攻略和两个示例。 实现步骤 在HTML中创建一个元素,用来包含选项卡切换按钮和内容区域。 在CSS中为选项卡切换按钮和内容区域定义样式。 在JavaScript中编写代码,给每个选项卡按钮添加点击事件,动态切换内容区域的显示。 下面是两个示例: 示例一 该示例实现点击选项卡切换按…

    Java 2023年6月15日
    00
  • Docker自动部署Apache Tomcat的方法

    Docker是一种容器化技术,它可以让我们更方便地管理和部署应用程序。在这篇攻略中,我将为您介绍如何使用Docker来快速、自动地部署Apache Tomcat容器。 准备工作 在开始之前,您需要先安装好Docker,可以去官网下载相应版本的安装程序,安装完毕后使用以下命令测试是否安装成功: docker –version 如果输出了Docker的版本信息…

    Java 2023年5月19日
    00
  • spring framework体系结构及模块jar依赖关系详解

    Spring Framework是一个开放源代码的轻量级应用程序框架。它是为了解决企业级应用程序开发的许多疑难问题而创建的。Spring框架采用了依赖注入和面向切面编程等技术,使得代码更加简洁,更加易于测试和维护。在Spring中,模块jar包的依赖关系非常重要,因为它们决定了应用程序的行为和性能。 Spring Framework体系结构及模块jar依赖关…

    Java 2023年5月19日
    00
  • Java 实战练习之网上电商项目的实现

    Java 实战练习之网上电商项目的实现攻略 准备工作 确保已安装JDK,建议使用JDK8以上版本。 确保已安装Maven,用于依赖管理和项目构建。 确认使用的开发工具,如:Eclipse、Intellij IDEA等。 在Github 上创建一个项目并关联到本地。 技术选型 后端框架:Spring Boot 数据库:MySQL ORM框架:MyBatis 前…

    Java 2023年5月18日
    00
  • cookie、session和java过滤器结合实现登陆程序

    实现登陆程序需要用到cookie、session和java过滤器,下面是实现登陆程序的完整攻略: 1.理解cookie和session Cookie是一小段文本信息,存在客户端浏览器上,用于存储一些关于用户的信息。一个浏览器对于同一个cookie的请求都会带上这个cookie。 Session是一种在服务器端保存用户数据的解决方案。Session的工作流程为…

    Java 2023年6月15日
    00
  • Java模拟多线程实现抢票代码实例

    以下是关于“Java模拟多线程实现抢票代码实例”的详细攻略: 什么是多线程 多线程是指在同一程序中,多个线程同时运行,实现多个任务同时执行的一种编程方式。在Java中,线程是比进程更小的执行单元,每个线程都可以独立地运行和完成自己的任务。 实现多线程的两种方式 继承Thread类 通过继承Thread类并重写它的run()方法来实现多线程。重写run()方法…

    Java 2023年5月18日
    00
  • Java中Thread.join()的使用方法

    下面我来详细讲解Java中Thread.join()的使用方法。 Thread.join()方法 Thread.join()方法是一个用于等待线程结束的方法。在执行线程时,可以调用join()方法,让当前线程等待被调用join()方法的线程执行完成后才继续往下执行。 语法 public final void join() throws Interrupted…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部