Java线程间的通信方式详解

Java线程间的通信方式详解

在Java中,线程间的通信是指两个或多个线程之间通过某种方式进行交流、协作的过程,Java线程间的通信主要有以下几种方式:

1.共享内存

共享内存是指多个线程之间共享同一块内存区域,通过修改该内存区域来实现线程之间的通信。Java中的共享内存通信方式有synchronizedvolatilewaitnotify等。

示例1:使用synchronized实现线程同步

public class ShareMemoryDemo {
    private static boolean flag = false;

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            while (true) {
                synchronized (ShareMemoryDemo.class) {
                    if (flag) {
                        System.out.println("线程1");
                        flag = false;
                        ShareMemoryDemo.class.notify();
                    } else {
                        try {
                            ShareMemoryDemo.class.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

        Thread t2 = new Thread(() -> {
            while (true) {
                synchronized (ShareMemoryDemo.class) {
                    if (!flag) {
                        System.out.println("线程2");
                        flag = true;
                        ShareMemoryDemo.class.notify();
                    } else {
                        try {
                            ShareMemoryDemo.class.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

        t1.start();
        t2.start();
    }
}

在上述示例中,flag变量被用作一个标记,用来表示两个线程之间的通信状态。线程1和线程2交替打印输出。

示例2:使用waitnotify实现生产者-消费者模型

import java.util.LinkedList;

public class ProducerConsumerDemo {
    private LinkedList<Integer> storage = new LinkedList<>();
    private final int MAX_SIZE = 10;

    public void produce() {
        while (true) {
            synchronized (storage) {
                while (storage.size() >= MAX_SIZE) {
                    try {
                        System.out.println("仓库已满,生产者等待...");
                        storage.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                int num = (int) (Math.random() * 100);
                storage.add(num);
                System.out.println("生产了一个产品: " + num);
                storage.notify();
            }
        }
    }

    public void consume() {
        while (true) {
            synchronized (storage) {
                while (storage.isEmpty()) {
                    try {
                        System.out.println("仓库已空,消费者等待...");
                        storage.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                int num = storage.removeFirst();
                System.out.println("消费了一个产品:" + num);
                storage.notify();
            }
        }
    }

    public static void main(String[] args) {
        ProducerConsumerDemo demo = new ProducerConsumerDemo();
        Thread producer = new Thread(() -> {
            demo.produce();
        });
        Thread consumer = new Thread(() -> {
            demo.consume();
        });
        producer.start();
        consumer.start();
    }
}

在上述示例中,使用LinkedList作为共享变量,生产者每次随机生成一个数字并存入LinkedList中,消费者每次从LinkedList中取出第一个数字并消费。如果LinkedList已满,则生产者线程等待,如果LinkedList为空,则消费者线程等待。

2. 消息传递

消息传递是指线程间通过发送消息的方式实现通信。Java中的消息传递通信方式主要有BlockingQueueSemaphore等。

示例1:使用BlockingQueue实现生产者-消费者模型

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueDemo {
    public static void main(String[] args) {
        BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);

        Thread producer = new Thread(() -> {
            while (true) {
                try {
                    int num = (int) (Math.random() * 100);
                    queue.put(num);
                    System.out.println("生产了一个产品: " + num);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread consumer = new Thread(() -> {
            while (true) {
                try {
                    int num = queue.take();
                    System.out.println("消费了一个产品:" + num);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        producer.start();
        consumer.start();
    }
}

在上述示例中,使用BlockingQueue作为消息传递方式进行线程间通信。生产者线程每次随机生成一个数字并存入BlockingQueue中,消费者线程每次从BlockingQueue中取出一个数字并消费,如果BlockingQueue已满,则生产者线程阻塞,如果BlockingQueue为空,则消费者线程阻塞。

示例2:使用Semaphore实现多线程限流

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(5);

        for (int i = 1; i <= 10; i++) {
            Thread t = new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "进入,当前还有" + semaphore.availablePermits() + "个许可");
                    Thread.sleep(1000);
                    semaphore.release();
                    System.out.println(Thread.currentThread().getName() + "离开,当前还有" + semaphore.availablePermits() + "个许可");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "线程" + i);
            t.start();
        }
    }
}

在上述示例中,使用Semaphore作为消息传递方式进行线程间通信,通过调用semaphore.acquire()获取一个许可,如果所有许可都已经被获取,则线程阻塞。线程执行完任务后,调用semaphore.release()释放许可。

3. 远程调用

远程调用是指通过网络传输调用远程计算机中的方法,实现跨计算机之间的通信。Java中的远程调用通信方式有RMIHessianHttp等。

对于远程调用的使用,这里不做详细的展开。

4. 信号量

信号量是指通过锁可以获取的许可数量控制同时访问某个资源的线程数量,实现对资源的并发访问控制。Java中的信号量通信方式有SemaphoreCountDownLatchCyclicBarrier等。

对于信号量的使用,这里已经在上述示例中有展开,不再重复。

总结

以上是Java线程间的通信方式的详细讲解和示例,不同的通信方式适合不同的场景,具体要根据项目需求和性能情况进行选择和应用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java线程间的通信方式详解 - Python技术站

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

相关文章

  • java String拼接时的问题汇总

    Java String拼接时的问题汇总 在 Java 中,String 类型是我们常用的数据类型之一,我们经常需要对字符串进行拼接操作。但是,在拼接过程中,我们也会遇到一些问题,比如性能问题、线程安全问题等。本文将会对 Java String 拼接时的问题进行梳理和解决。 问题一:使用 + 进行字符串拼接,性能问题 在 Java 中,我们可以使用 + 符号对…

    Java 2023年5月27日
    00
  • Sprint Boot @JsonIgnore使用方法详解

    @JsonIgnore是Spring Boot中的一个注解,用于标记某个字段或方法不参与序列化或反序列化。在本文中,我们将详细介绍@JsonIgnore注解的作用和使用方法,并提供两个示例。 @JsonIgnore注解的作用 @JsonIgnore注解用于标记某个字段或方法不参与序列化或反序列化。当使用@JsonIgnore注解标记某个字段或方法时,该字段或…

    Java 2023年5月5日
    00
  • 深入理解spring多数据源配置

    下面是详细讲解“深入理解Spring多数据源配置”的完整攻略: 1. Spring多数据源配置介绍 Spring多数据源配置是指在一个应用程序中配置多个数据库,实现数据的读写分离、负载均衡等功能的技术。下面我们来详细介绍Spring多数据源的配置步骤。 2. Spring多数据源配置步骤 2.1 创建数据源配置类 在Java项目中,我们需要首先创建一个数据源…

    Java 2023年5月20日
    00
  • java中使用数组进行模拟加密的方法

    Java中使用数组进行模拟加密的方法 对于小规模的数据加密,可以使用Java的数组进行模拟加密。具体实现方法如下: 首先,定义一个加密数组,用于模拟加密过程。例如: int[] encryptArray = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0}; 这个数组中的元素可以是0-9的任意数,用于表示加密后的数字。可以根据需要更改数组中的元素…

    Java 2023年5月26日
    00
  • 微信小程序实现表格前后台分页

    下面是微信小程序实现表格前后台分页的完整攻略: 1. 准备工作 安装微信开发者工具 新建小程序项目 安装 wx-server-sdk(用于云函数开发) 2. 前端页面设计 使用 table 标签展示表格 使用 navigator 标签实现分页 先给出一个示例代码: <view> <table> <thead> <tr…

    Java 2023年5月23日
    00
  • 详解Java向服务端发送文件的方法

    详解Java向服务端发送文件的方法 在Java编程中,我们经常需要向服务端发送文件,比如我们需要上传用户的头像、简历等等。本文将详细讲解Java向服务端发送文件的方法。 1. 使用Java中的URLConnection发送文件 Java中的URLConnection类可以用来向服务端发送文件。下面是示例代码: import java.io.File; imp…

    Java 2023年5月19日
    00
  • JavaWeb使用Cookie模拟实现自动登录功能(不需用户名和密码)

    下面是JavaWeb使用Cookie模拟实现自动登录功能的完整攻略。 什么是Cookie 在讲解如何使用Cookie实现自动登录功能之前,我们首先来了解一下什么是Cookie。Cookie是一种在Web客户端(通常是在浏览器中)存储数据的机制。服务器通过发送一个名为Set-Cookie的HTTP头部给浏览器以保存Cookie,然后浏览器会在后续的请求中将该C…

    Java 2023年6月15日
    00
  • SpringBoot统一功能处理的方式详解

    Spring Boot统一功能处理的方式详解 Spring Boot是一个流行的Java框架,可以帮助开发人员快速构建和部署应用程序。在开发过程中,我们经常需要实现一些通用的功能,例如异常处理、日志记录、安全性等。本文将详细讲解如何使用Spring Boot实现统一功能处理,包括全局异常处理、日志记录、安全性等。 1. 全局异常处理 在Web应用程序中,异常…

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