Java多线程中的wait/notify通信模式实例详解

yizhihongxing

接下来我将为大家详细讲解“Java多线程中的wait/notify通信模式实例详解”。

一、前言

在Java多线程编程中,线程间通信是一项重要的技术。wait/notify通信模式是一种应用广泛的线程间通信方法。通过wait/notify通信模式,线程能够在不使用轮询的情况下进行线程间的信息传递和共享,提高了线程间的运行效率,降低了系统资源的消耗。

本篇攻略将为大家介绍Java多线程中的wait/notify通信模式的实例详解。通过两个示例,将带领大家深入了解wait/notify通信模式的使用方法和注意事项。

二、示例一:生产者/消费者模式

生产者/消费者模式是多线程编程中一个非常常见的模式。在该模式中,生产者线程负责生产数据,消费者线程负责消费数据。生产者线程将数据生产出来后,需要将数据传递给消费者线程,消费者线程等待生产者线程生产数据,然后再进行消费。在该模式中,就需要用到wait/notify通信模式。

以下是实现生产者/消费者模式的方法:

  1. 定义一个共享数据的缓冲区,该缓冲区可以存放多个数据。
  2. 定义一个生产者线程,该线程负责生产数据,并将数据放入共享数据缓冲区中。
  3. 定义一个消费者线程,该线程负责从共享数据缓冲区中取数据,并进行消费。
  4. 在生产者线程中,使用synchronized关键字对共享数据缓冲区进行加锁。
  5. 在生产者线程中,当共享数据缓冲区中的数据满了时,使用wait方法等待。
  6. 在生产者线程中,当共享数据缓冲区有空位时,使用notify方法通知消费者线程可以取数据了。
  7. 在消费者线程中,使用synchronized关键字对共享数据缓冲区进行加锁。
  8. 在消费者线程中,当共享数据缓冲区中没有数据时,使用wait方法等待。
  9. 在消费者线程中,当共享数据缓冲区有数据时,使用notify方法通知生产者线程可以生产数据了。

以下是示例代码:

public class ProducerConsumerDemo {
    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        new Thread(new Producer(buffer)).start();
        new Thread(new Consumer(buffer)).start();
    }
}

class Buffer {
    private int[] data = new int[10];
    private int count = 0;

    public synchronized void put(int num) {
        if (count == data.length) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        data[count] = num;
        count++;
        notify();
    }

    public synchronized int get() {
        if (count == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count--;
        int num = data[count];
        notify();
        return num;
    }
}

class Producer implements Runnable {
    private Buffer buffer;

    public Producer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            buffer.put(i);
            System.out.println("生产者生产了:" + i);
            try {
                Thread.sleep((int) (Math.random() * 200));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Consumer implements Runnable {
    private Buffer buffer;

    public Consumer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            int num = buffer.get();
            System.out.println("消费者消费了:" + num);
            try {
                Thread.sleep((int) (Math.random() * 200));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在该示例中,我们定义了一个Buffer类作为共享数据的缓冲区,使用synchronized关键字对该类进行加锁,保证了线程安全。生产者线程使用wait方法等待共享数据缓冲区有空位,使用notify方法通知消费者线程可以取数据了。消费者线程使用wait方法等待共享数据缓冲区有数据,使用notify方法通知生产者线程可以生产数据了。在运行该示例时,可以看到生产者线程和消费者线程交替运行,保证了线程的正确性。

三、示例二:实现线程顺序执行

在Java多线程编程中,线程的运行顺序是随机的,我们无法直接控制线程的运行顺序。但是使用wait/notify通信模式,我们可以实现线程的顺序执行。

以下是实现线程顺序执行的方法:

  1. 定义多个线程,每个线程都需要有自己的标识符。
  2. 在每个线程中,使用synchronized关键字对共享对象进行加锁。
  3. 在每个线程中,使用while循环进行判断,当标识符不等于自己时,使用wait方法等待。
  4. 当线程执行完毕后,改变标识符并使用notifyAll方法通知其他线程执行。

以下是示例代码:

public class ThreadSequenceDemo {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new SequenceThread(lock, i);
            threads[i].start();
        }
    }
}

class SequenceThread extends Thread {
    private Object lock;
    private int id;

    public SequenceThread(Object lock, int id) {
        this.lock = lock;
        this.id = id;
    }

    @Override
    public void run() {
        synchronized (lock) {
            while (id != Sequence.order) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("Thread " + id + " is running.");
            Sequence.order++;
            lock.notifyAll();
        }
    }
}

class Sequence {
    public static int order = 0;
}

在该示例中,我们定义了一个SequenceThread类作为线程的实现类,使用synchronized关键字对共享对象进行加锁,保证线程安全。在每个线程中,使用while循环进行判断当前线程的标识符是否等于Sequence.order顺序,如果不等于,则使用wait方法等待。当线程执行完毕后,改变Sequence.order标识符并使用notifyAll方法通知其他线程执行。

以上就是本文对“Java多线程中的wait/notify通信模式实例详解”的介绍,希望本文能够对大家有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程中的wait/notify通信模式实例详解 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • js里面的变量范围分享

    JavaScript变量的作用域 在JavaScript中,变量的作用域决定了它在代码中的可见性和可访问性。了解变量的作用域对于编写可维护和可扩展的代码非常重要。JavaScript中有三种类型的作用域:全局作用域、函数作用域和块级作用域。 全局作用域 全局作用域是在整个JavaScript代码中都可访问的作用域。在全局作用域中声明的变量可以在代码的任何地方…

    other 2023年7月29日
    00
  • Java下http下载文件客户端和上传文件客户端实例代码

    让我为您详细讲解Java下http下载文件客户端和上传文件客户端实例代码的完整攻略。 一、http下载文件客户端代码示例 1.1 通过Java SE自带库实现 使用Java SE自带库实现简单的http下载文件客户端代码,只需要用到Java SE自带的URL和HttpURLConnection两个类即可。 import java.io.BufferedInp…

    other 2023年6月25日
    00
  • 如何重设/清除/删除neo4j数据库?

    已经回答了您的问题,请查看上面的回答。如果您有任何其他问题或需要进一步的帮助,请告诉我。

    other 2023年5月7日
    00
  • C/C++中数据类型转换详解及其作用介绍

    C/C++中数据类型转换详解及其作用介绍 前言 在C/C++开发中,数据类型的转换十分普遍。正确地掌握数据类型转换的方法和规则,是写出高效且无bug的代码的重要基础。本文将详细介绍C/C++中数据类型转换的相关知识,并提供实例以加深理解。 数据类型转换方法 C/C++中的数据类型转换主要有两种方法:隐式转换和显式转换。 隐式转换 隐式转换是指在代码中不需要显…

    other 2023年6月26日
    00
  • linux分区规划 linux 硬盘分区规划介绍

    Linux 分区规划指南 在安装Linux系统的时候,磁盘的分区规划是非常重要的一部分。正确的分区规划决定了系统的性能和稳定性,也对系统后续的管理和维护产生影响。本文旨在介绍如何规划磁盘分区来安装Linux系统。 分区类型 在规划分区前,需要先了解几种不同类型的分区: 主分区: 一块硬盘最多可以有四个主分区。其中一个主分区可以被扩展为一个或多个逻辑分区。 扩…

    other 2023年6月27日
    00
  • TPLink路由器隐藏wifi用户名的方法

    关于“TPLink路由器隐藏wifi用户名的方法”的完整攻略,我来详细讲解一下。 步骤一:打开TPLink路由器的管理页面 首先,我们需要打开TPLink路由器的管理界面。一般情况下,我们可以在浏览器的地址栏里输入“192.168.1.1”(也可能是“192.168.0.1”)来进入。登录时需要输入用户名和密码。如果你从未更改过路由器的管理密码,那么可以尝试…

    other 2023年6月27日
    00
  • Java调用第三方接口封装实现

    下面是详细讲解“Java调用第三方接口封装实现”的完整攻略: 一、准备工作 在调用第三方接口前,需要完成如下准备工作: 确认接口文档:根据接口文档,了解接口的请求方式、方法参数、返回值等信息。 申请接口权限:有些接口需要事先向服务商申请并获得接口访问权限。 找到接口URL:接口URL是调用接口的重要参数,需要通过接口文档或者接口服务商提供的文档找到。 选择合…

    other 2023年6月25日
    00
  • Kotlin语言使用WebView示例介绍

    Kotlin语言使用WebView示例介绍 简介 WebView是Android平台上的一个重要组件,它可以在应用程序中显示网页内容。Kotlin语言提供了简洁而强大的方式来使用WebView组件。本攻略将详细介绍如何在Kotlin语言中使用WebView,并提供两个示例说明。 示例一:加载网页 以下是一个简单的示例,演示了如何在Kotlin中使用WebVi…

    other 2023年9月6日
    00
合作推广
合作推广
分享本页
返回顶部