首页 > 编程语言 >Java中的线程通信详解

Java中的线程通信详解

时间:2024-07-13 15:19:24浏览次数:9  
标签:Java Thread value 详解 线程 notify new public

Java中的线程通信详解

大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!

在多线程编程中,线程之间的通信是一个重要且复杂的主题。为了确保多线程程序的正确性和效率,线程需要能够互相通信并协调工作。Java 提供了多种方式来实现线程间的通信,如 wait()notify()notifyAll() 方法,以及更高级的并发工具类。本文将详细介绍 Java 中的线程通信,涵盖基本概念、常用方法和具体代码示例。

一、基本概念

线程通信是指线程之间通过某种机制传递信息,以协调它们之间的行为。Java 中提供了内置的线程通信机制,包括 wait()notify()notifyAll() 方法,这些方法都是 Object 类的一部分,每个对象都可以作为线程通信的锁。

二、wait()notify()notifyAll()方法

  1. wait()方法

wait() 方法使当前线程进入等待状态,直到其他线程调用 notify()notifyAll() 方法唤醒它。该方法必须在同步块或同步方法中调用,否则会抛出 IllegalMonitorStateException 异常。

  1. notify()方法

notify() 方法唤醒一个正在等待该对象监视器的线程。如果有多个线程在等待,则选择其中一个线程唤醒。被唤醒的线程在获取对象的监视器后,才能继续执行。

  1. notifyAll()方法

notifyAll() 方法唤醒所有正在等待该对象监视器的线程。被唤醒的线程在获取对象的监视器后,才能继续执行。

三、代码示例

以下示例演示了如何使用 wait()notify()notifyAll() 方法进行线程通信。

1. 生产者-消费者模型

package cn.juwatech.threads;

import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumerExample {
    private static final int CAPACITY = 5;
    private final Queue<Integer> queue = new LinkedList<>();
    private final Object lock = new Object();

    public static void main(String[] args) {
        ProducerConsumerExample example = new ProducerConsumerExample();
        Thread producerThread = new Thread(example.new Producer());
        Thread consumerThread = new Thread(example.new Consumer());

        producerThread.start();
        consumerThread.start();
    }

    class Producer implements Runnable {
        @Override
        public void run() {
            int value = 0;
            while (true) {
                synchronized (lock) {
                    while (queue.size() == CAPACITY) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    queue.offer(value);
                    System.out.println("Produced: " + value);
                    value++;
                    lock.notify();
                }
            }
        }
    }

    class Consumer implements Runnable {
        @Override
        public void run() {
            while (true) {
                synchronized (lock) {
                    while (queue.isEmpty()) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    int value = queue.poll();
                    System.out.println("Consumed: " + value);
                    lock.notify();
                }
            }
        }
    }
}

在这个示例中,生产者线程生成整数并将其放入队列中,而消费者线程从队列中取出整数并进行消费。wait()notify() 方法用于协调生产者和消费者之间的工作。

四、使用更高级的并发工具类

Java 提供了更高级的并发工具类,如 BlockingQueueSemaphoreCountDownLatchCyclicBarrier,它们简化了线程间的通信和同步。

1. 使用 BlockingQueue 实现生产者-消费者模型

package cn.juwatech.threads;

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

public class BlockingQueueExample {
    private static final int CAPACITY = 5;
    private final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(CAPACITY);

    public static void main(String[] args) {
        BlockingQueueExample example = new BlockingQueueExample();
        Thread producerThread = new Thread(example.new Producer());
        Thread consumerThread = new Thread(example.new Consumer());

        producerThread.start();
        consumerThread.start();
    }

    class Producer implements Runnable {
        @Override
        public void run() {
            int value = 0;
            while (true) {
                try {
                    queue.put(value);
                    System.out.println("Produced: " + value);
                    value++;
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    class Consumer implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    int value = queue.take();
                    System.out.println("Consumed: " + value);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}

在这个示例中,BlockingQueue 处理了同步和通信逻辑,使得代码更加简洁和易于理解。

2. 使用 Semaphore 控制线程访问

Semaphore 是一种计数信号量,用于控制同时访问特定资源的线程数量。

package cn.juwatech.threads;

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    private static final int PERMITS = 3;
    private final Semaphore semaphore = new Semaphore(PERMITS);

    public static void main(String[] args) {
        SemaphoreExample example = new SemaphoreExample();
        for (int i = 0; i < 10; i++) {
            new Thread(example.new Worker(i)).start();
        }
    }

    class Worker implements Runnable {
        private final int workerId;

        Worker(int workerId) {
            this.workerId = workerId;
        }

        @Override
        public void run() {
            try {
                semaphore.acquire();
                System.out.println("Worker " + workerId + " is working...");
                Thread.sleep(2000);
                System.out.println("Worker " + workerId + " finished working.");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                semaphore.release();
            }
        }
    }
}

在这个示例中,Semaphore 控制同时最多只有三个线程可以访问资源,其余线程必须等待。

五、线程通信的最佳实践

  1. 避免忙等待:使用 wait()notify()notifyAll() 或并发工具类避免忙等待,提高效率。
  2. 适当使用锁和同步:确保共享资源的安全访问,避免死锁。
  3. 选择合适的并发工具类:根据具体需求选择合适的并发工具类,简化线程通信和同步逻辑。

通过以上内容,我们详细介绍了 Java 中的线程通信机制,包括基本概念、常用方法及其具体代码示例,并探讨了使用更高级的并发工具类实现线程通信的方法。掌握这些知识,能够帮助我们编写出更加高效和可靠的多线程程序。

著作权归聚娃科技微赚淘客系统开发者团队,转载请注明出处!

标签:Java,Thread,value,详解,线程,notify,new,public
From: https://www.cnblogs.com/szk123456/p/18300154

相关文章

  • Java中标识符和关键字
    1.标识符publicclassHelloWorld{publicstaticvoidmain(String[]args){System.out.println("Hello,world");}}上述代码中在publicclass后面的HelloWorld称为类名,main称为方法名,也可以将其称为标识符,即:在程序中由用户给类名、方法名或者变量所取的名字。【......
  • 初识Java的main方法
    上文我们了解了Java语言的相关发展和Java的实用领域,此文我们从Java的main方法开始了解Java吧!1.main方法示例publicclassHelloWorld{publicstaticvoidmain(String[]args){System.out.println("Hello,world");}}图解:如上展示的就是最简单的一个Java程序,可......
  • Java异常详解及自定义异常
    认识异常,掌握异常处理主要的5个关键字:throw、try、catch、final、throws并掌握自定义异常目录1、异常概念与体系结构1、1异常的概念1、2异常体系结构 1、3异常的分类编译时异常:运行时异常:2、异常处理 2、1防御式编程2、2异常的抛出2.3异常的捕获2.3.1异常声......
  • 【java登录锁定功能】redis实现登录失败锁定账号
    登录失败(账号密码<5次时不提示),>=5次时,锁定时间5min,最高密码错误次数为10,第十次密码输入错误后,提醒,“账号已停用,请联系管理员开通”,次日0时,重新计算错误次数代码实现publicstaticStringLOGIN_FAIL_LOCK="login:error:count:";publicstaticStringLOGIN......
  • 【华为OD】D卷真题100分:内存资源分配 Java代码实现[思路+代码]
    【华为OD】2024年C、D卷真题集:最新的真题集题库C/C++/Java/python/JavaScript【华为OD】2024年C、D卷真题集:最新的真题集题库C/C++/Java/python/JavaScript-CSDN博客JS、C、Java、python、C++代码实现:【华为OD】D卷真题100分:内存资源分配JavaScript代码实现[思路+代码]-C......
  • MYSQL 从入门到熟练 详解(看这一篇就够啦)
    一、MYSQL入门1.数据库概述(1)定义数据库(Database)是“按照数据结构来组织、存储和管理数据的仓库”。它是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。数据库中的数据按一定的数据模型组织、描述和存储,具有较小的数据冗余、较高的数据独立性和......
  • JAVA@Transactional常用失效场景
    @Transactional(rollbackFor={RuntimeException.class,Error.class})@Overridepublicbooleancreate(){create1();create2();returntrue;}publicvoidcreate1(){Studentstudent=newStudent();student.setNa......
  • JAVA初级之File文件类
    目录1、概述2、构造方法 3、常用方法3.1获取功能的方法 3.2绝对路径和相对路径 3.3判断功能的方法 3.4创建删除的方法 3.5对目录的遍历4、经典案例4.1查询某个目录下所有的文件。 4.2 找到电脑中所有以avi结尾的电影。1、概述        在......
  • windows使用bat文件 执行java程序
    java开发的程序想在windows上运行。首先要安装对应的java运行环境。然后创建一个 ***.bat文件,写入下面代码,双击它。@echoofftitleLSpbxServercd\d:cd"javaapp\LSpbxServer"java-jarLSpbxServer.jarpausetitleLSpbxServer是这个cmd.exe窗体的标题,同时......
  • 基于Java+Vue的采购管理系统:实现采购业务数字化变革(整套代码)
    前言:采购管理系统是一个综合性的管理平台,旨在提高采购过程的效率、透明度,并优化供应商管理。以下是对各个模块的详细解释:一、供应商准入供应商注册:供应商通过在线平台进行注册,填写基本信息和资质文件。资质审核:系统对供应商提交的资质文件进行自动或人工审核,确保供应商符......