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日

相关文章

  • echarts整合多个类似option的方法实例

    下面我将为您详细讲解“echarts整合多个类似option的方法实例”的完整攻略,主要分为以下几步进行。 1. 确认需求 在开始实现之前,我们首先需要确认我们的需求是什么。假设我们需要实现一个折线图,我们希望可以通过选择不同的时间段,动态的显示不同的数据,例如按天、按周、按月等显示数据。 2. 构建数据 为了实现我们的需求,我们需要构建一个数据对象,来保存…

    Java 2023年6月15日
    00
  • Java中System.currentTimeMillis()计算方式与时间单位转换讲解

    下面是Java中System.currentTimeMillis()计算方式与时间单位转换讲解的完整攻略。 1. System.currentTimeMillis()计算方式 在Java中,我们可以通过System.currentTimeMillis()方法获取当前的毫秒数,这个毫秒数表示从1970年1月1日00:00:00 GMT起到现在的时间间隔。 这个…

    Java 2023年5月20日
    00
  • Java移动文件夹及其所有子文件与子文件夹

    要在Java代码中移动文件夹及其所有子文件和子文件夹,可以使用Java自带的nio库中的类和方法。以下是完整攻略: 1. 导入nio库 在Java代码中首先需要导入nio库,即在代码文件顶部加入以下语句: import java.nio.file.*; 2. 定义方法 定义一个方法,在该方法中传入需要移动的文件夹的路径。 public static void…

    Java 2023年5月20日
    00
  • SpringBoot 枚举类型的自动转换的实现

    关于Spring Boot枚举类型的自动转换实现,我们可以从以下几个方面进行讲解: 1.枚举类型的定义 在Spring Boot应用中,我们可以通过Java中的枚举类型来定义一个特定的常量集合,例如: public enum Color { RED, GREEN, BLUE; } 2.自动转换的实现 Spring Boot通过Type Conversion …

    Java 2023年5月26日
    00
  • Java多线程——基础概念

    Java多线程——基础概念 什么是进程和线程 在操作系统中,一个正在运行的程序称为进程(process),进程可以拥有多个相互独立执行流程,称为线程(thread)。一个进程中至少有一个主线程。 为什么需要使用多线程 多线程的主要目的是提高程序的效率,特别是在当程序需要同时执行多个耗时操作时,可以通过多线程将这些操作并发地执行,提高整个程序的执行效率。同时,…

    Java 2023年5月19日
    00
  • Spring Boot教程之提高开发效率必备工具lombok

    关于“Spring Boot教程之提高开发效率必备工具Lombok”的攻略,可以分成以下几个部分进行讲解: Lombok是什么 Lombok的使用方法 Lombok的优点 Lombok的缺点 示例1:使用@Data注解简化Java Bean的实现 示例2:使用@Log注解快速添加日志功能 Lombok是什么 Lombok是一个Java库,可以通过注解的方式自…

    Java 2023年5月19日
    00
  • springboot 使用 minio的示例代码

    下面是详细的攻略过程。 使用 Minio 存储文件 Minio是一个分布式对象存储服务,除了能提供文件存储、数据备份和归档之外,还能快速实现容量扩展。 使用 Minio 前需要先创建一个存储桶。 val minioEndpoint: String val minioAccessKey: String val minioSecretKey: String va…

    Java 2023年5月20日
    00
  • Java内部类原理、概述与用法实例详解

    Java内部类原理、概述与用法实例详解 Java中的内部类是指嵌套在另外一个类内部的类,它们提供了更好的封装和代码组织方式。本文将详细讲解Java内部类的原理、概述和用法实例,并提供两个示例来说明其使用和优势。 内部类原理 Java中的内部类实际上是一种成员类,它与其他成员变量和成员方法一样隶属于其外围类,并可以访问外围类的私有数据和方法,甚至可以访问到其外…

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