Java多线程通信wait()和notify()代码实例

Java多线程通信wait()和notify()代码实例

目录

介绍

在Java多线程编程中,多个线程之间需要进行通信,来实现协作完成任务。Java提供了一种机制,即wait()和notify()方法,用于实现多线程之间的通信。

wait()方法和notify()方法

wait()和notify()方法属于Object类,可以用于实现线程之间的通信。其中,wait()方法是使当前执行的线程进入等待状态(阻塞),知道其他线程调用notify()或notifyAll()方法唤醒该线程为止。而notify()方法则是唤醒等待中的线程。

wait()方法和notify()方法必须在同步块或同步方法中调用,并且必须针对同一对象进行调用,否则会抛出IllegalMonitorStateException异常。

wait()和notify()方法的用法

wait()方法和notify()方法一般是配合使用,以实现一些特定的多线程编程模型。一般的使用方式如下:

synchronized(obj) {
    while(条件不满足) {
        obj.wait(); // 线程阻塞
    }
    // 执行响应的操作
    // ...
    // 操作完成后,唤醒其他线程
    obj.notifyAll();
}

wait()方法主要用于等待条件,等待其他线程对此对象发出notify()或notifyAll()方法的调用,使得该线程退出等待状态。

示例说明

示例1:打印奇偶数

我们可以用wait()和notify()方法来实现一个简单的多线程任务,即循环打印从1到100的数字,其中偶数由一个线程打印,奇数由另一个线程打印。具体代码如下:

public class Main {
    public static void main(String[] args) {
        Object obj = new Object();
        Thread t1 = new Thread(new Printer(obj, true)); // 打印奇数的线程
        Thread t2 = new Thread(new Printer(obj, false)); // 打印偶数的线程
        t1.start();
        t2.start();
    }
}

class Printer implements Runnable {
    private boolean isOdd; // 是否打印奇数
    private Object obj;
    private int i = 1;

    public Printer(Object obj, boolean isOdd) {
        this.obj = obj;
        this.isOdd = isOdd;
    }

    public void run() {
        while(i <= 100) {
            synchronized(obj) {
                while((i % 2 == 0) == isOdd) {
                    try {
                        obj.wait(); // 等待
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + ": " + i);
                i++;
                obj.notifyAll(); // 唤醒其他线程
            }
        }
    }
}

在以上代码中,我们创建了一个Printer线程类,该线程类的作用是从1到100依次打印出来,一个线程负责打印奇数,另一个线程负责打印偶数。该线程类的run()方法中使用了wait()和notify()实现了线程之间的同步,确保奇数和偶数依次打印。

示例2:生产者和消费者模型

生产者和消费者模型是指一个线程负责生产数据,另一个线程负责消费数据的一种模型。我们可以用wait()和notify()方法来实现生产者和消费者模型,具体代码如下:

public class Main {
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        Object lock = new Object();
        Thread producer = new Thread(new Producer(queue, lock));
        Thread consumer = new Thread(new Consumer(queue, lock));
        producer.start();
        consumer.start();
    }
}

class Producer implements Runnable {
    private Queue<Integer> queue;
    private Object lock;

    public Producer(Queue<Integer> queue, Object lock) {
        this.queue = queue;
        this.lock = lock;
    }

    public void run() {
        while(true) {
            int num = (int)(Math.random() * 100);
            synchronized(lock) {
                while(queue.size() >= 10) { // 如果队列已满,等待
                    try {
                        lock.wait();
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                queue.offer(num);
                System.out.println(Thread.currentThread().getName() + " 生产: " + num);
                lock.notifyAll(); // 唤醒其他线程
            }
        }
    }
}

class Consumer implements Runnable {
    private Queue<Integer> queue;
    private Object lock;

    public Consumer(Queue<Integer> queue, Object lock) {
        this.queue = queue;
        this.lock = lock;
    }

    public void run() {
        while(true) {
            synchronized(lock) {
                while(queue.isEmpty()) { // 如果队列为空,等待
                    try {
                        lock.wait();
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                int num = queue.poll();
                System.out.println(Thread.currentThread().getName() + " 消费: " + num);
                lock.notifyAll(); // 唤醒其他线程
            }
        }
    }
}

在以上代码中,我们创建了Producer和Consumer两个线程类,分别负责生产和消费数据。在Producer线程的run()方法中,我们使用了while循环,不停地生产数据,并使用wait()和notify()方法实现线程之间的同步,确保在队列已满的情况下等待,如果队列不满,就将数据添加到队列中。在Consumer线程的run()方法中,也是用while循环不断地消费数据,并使用wait()和notify()方法实现线程之间的同步,确保在队列为空的情况下等待,如果队列不为空,就从队列中取出数据并消费。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程通信wait()和notify()代码实例 - Python技术站

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

相关文章

  • MyBatis运行找不到xml资源文件

    MyBatis运行找不到xml资源文件 运行报错: 报错原因:程序运行后,没有将 src/main/java 目录下的资源文件(xml、properties等等)导出到 target工作目录下,所以程序找不到 java目录: 运行后的target目录:可以看到并没有 MonsterMapper.xml文件 解决方法: Maven项目在 pom.xml 文件中…

    Java 2023年4月23日
    00
  • Sprint Boot @Import使用方法详解

    在Spring Boot中,@Import注解是一种用于导入其他配置类或组件的注解。使用@Import注解可以将其他配置类或组件导入到当前配置类中,从而实现组件的复用和模块化。本文将详细介绍@Import注解的作用和使用方法,并提供两个示例说明。 @Import注解的作用 在Spring Boot中,@Import注解的作用是将其他配置类或组件导入到当前配置…

    Java 2023年5月5日
    00
  • jquery 隐藏与显示tr标签示例代码

    下面是关于jQuery隐藏与显示<tr>标签的攻略。 前置要求 在使用本教程前,需要确保您已经了解以下内容: HTML基础 CSS基础 jQuery基础 操作步骤 方法一:使用隐藏和显示方法 在jQuery中,可以使用hide()方法隐藏元素,show()方法显示元素。将这两个方法应用于<tr>标签,即可实现隐藏和显示<tr&g…

    Java 2023年6月16日
    00
  • Hibernate基于ThreadLocal管理Session过程解析

    当我们使用Hibernate进行对象关系映射时,我们常常需要处理Session对象的创建、使用和关闭等生命周期的管理。为了确保线程安全和线程隔离,通常采用ThreadLocal变量来管理Session对象。Hibernate基于ThreadLocal管理Session的过程如下: 创建ThreadLocal对象 我们可以使用如下代码创建一个ThreadLoc…

    Java 2023年5月19日
    00
  • Java中关于http请求获取FlexManager某设备分组监控点

    在Java中发送HTTP请求,可以使用Java内置的HttpURLConnection类或者第三方库如OkHttp、HttpClient等。以下是获取FlexManager某设备分组监控点的攻略。 准备工作 在发送HTTP请求前,需要导入相应的依赖包,例如使用OkHttp时,需要在pom.xml中添加以下依赖: <dependency> <…

    Java 2023年5月26日
    00
  • MyEclipse怎么关闭.html.jsp的可视化编辑器?

    要关闭 MyEclipse 中 HTML 和 JSP 的可视化编辑器,可以按照以下步骤进行操作: 打开 MyEclipse 编辑器,找到菜单栏中的“Windows”选项,并选择“Preferences”。 在弹出的“Preferences”窗口中,选择“Web”下的“Editors”选项。 在“Editors”选项中,可以看到“HTML”和“JSP”的编辑器…

    Java 2023年6月15日
    00
  • java环境变量的配置方法图文详解【win10环境为例】

    Java环境变量的配置方法图文详解(Win10环境为例) Java编程利用JDK和JRE提供的库来开发和运行Java程序。在安装Java后,要配置Java环境变量,才能在命令行模式下运行Java程序。 下面是Java环境变量在Win10环境下的配置方法: 1. 下载JDK 首先,从官网上下载对应平台的JDK安装包。 示例说明:下载JDK8u291 Windo…

    Java 2023年5月23日
    00
  • SpringBoot 集成 Quartz + MySQL

    Quartz 简单使用Java SpringBoot 中,动态执行 bean 对象中的方法 源代码地址 => https://gitee.com/VipSoft/VipBoot/tree/develop/vipsoft-quartz 工作原理解读 只要配置好 DataSource Quartz 会自动进行表的数据操作, 添加 Quartz Job 任务…

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