当需要多个线程共同完成一件任务,而且需要有规律的执行,那么多个线程之间需要一定的通信机制,可以协调他们的工作,以此实现多线程共同操作一份数据。

1 等待唤醒机制

这是一种线程间的协作机制,与争夺锁的竞争机制相对应,当一个线程满足某个条件时,就进入等待状态( wait/wait(m) ),等到其他线程执行完指定的代码后,再将其唤醒,或者可以指定时间,到时间了自动唤醒,有多个线程等待时,如果有需要,可以notifyAll()唤醒所有等待的线程,wait/notify就是一种线程间的协助机制。

wait()

  • 作用:使当前线程等待,直到其他线程调用相同对象的 notify()notifyAll() 方法,或者线程被中断。
  • 使用场景:当一个线程需要等待某个条件发生时,比如资源可用、状态改变等。
  • 条件:调用 wait() 方法时,当前线程必须持有该对象的监视器锁(synchronized),否则会抛出 IllegalMonitorStateException 异常。
synchronized (sharedObject) {
while (!condition) {
sharedObject.wait(); // 释放锁并等待
}
// 条件满足后的操作
}

notify()

  • 作用:唤醒在该对象上等待的一个线程。如果有多个线程在等待,则随机选择一个线程唤醒。
  • 使用场景:在某个条件被满足时,通知一个等待的线程继续执行。
synchronized (sharedObject) {
// 修改条件
sharedObject.notify(); // 唤醒一个等待线程
}

notifyAll()

  • 作用:唤醒在该对象上等待的所有线程。
  • 使用场景:当条件变化可能影响所有等待线程时,使用 notifyAll() 确保所有线程都有机会重新检查条件。
synchronized (sharedObject) {
// 修改条件
sharedObject.notifyAll(); // 唤醒所有等待线程
}

2 例子

2.1 两个线程共同卖票,一人一张


public class Ticket { public static void main(String[] args) { TicketTask t1 = new TicketTask();
TicketTask t2 = new TicketTask(); t1.start();
t2.start(); } static class TicketTask extends Thread { static int ticket = 200;
static final Object lock = new Object(); @Override
public void run() {
while (true) { synchronized (lock) {
lock.notifyAll(); if (ticket > 0) {
System.out.println(Thread.currentThread().getName() +" " + ticket);
ticket--;
}
else {
break;
} try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} }
}
}
}

2.2 两个线程共同交替从1加到100

public class TestAdd {

    static int i = 0;

    public static void main(String[] args) {

        Runnable runnable = new Runnable() {
@Override
public void run() {
while (true) {
synchronized (this){
this.notify();
if (i < 100) {
System.out.println(Thread.currentThread().getName() + "---" + ++i);
}
else {
break;
} try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} } }
}; new Thread(runnable).start();
new Thread(runnable).start(); } }

Java线程的通信的更多相关文章

  1. Java线程间通信-回调的实现方式

    Java线程间通信-回调的实现方式   Java线程间通信是非常复杂的问题的.线程间通信问题本质上是如何将与线程相关的变量或者对象传递给别的线程,从而实现交互.   比如举一个简单例子,有一个多线程的 ...

  2. Java线程之间通信

    用多线程的目的:更好的利用CPU的资源.因为所有的多线程代码都可以用单线程来实现. 多线程:指的是这个程序(一个进程)运行时产生了不止一个线程. 并行:多个CPU实例或者多台机器同时执行一段处理逻辑, ...

  3. Java线程间通信之wait/notify

    Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式.我们来看下相关定义: w ...

  4. java线程间通信:一个小Demo完全搞懂

    版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程系列文章只是自己知识的总结梳理,都是最基础的玩意,已经掌握熟练的可以绕过. 一.从一个小Demo说起 上篇我们聊到了Java多线程的同步 ...

  5. Java——线程间通信

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  6. 说说Java线程间通信

    序言 正文 [一] Java线程间如何通信? 线程间通信的目标是使线程间能够互相发送信号,包括如下几种方式: 1.通过共享对象通信 线程间发送信号的一个简单方式是在共享对象的变量里设置信号值:线程A在 ...

  7. 说说 Java 线程间通信

    序言 正文 一.Java线程间如何通信? 线程间通信的目标是使线程间能够互相发送信号,包括如下几种方式: 1.通过共享对象通信 线程间发送信号的一个简单方式是在共享对象的变量里设置信号值:线程A在一个 ...

  8. java线程间通信1--简单实例

    线程通信 一.线程间通信的条件 1.两个以上的线程访问同一块内存 2.线程同步,关键字 synchronized 二.线程间通信主要涉及的方法 wait(); ----> 用于阻塞进程 noti ...

  9. Java——线程间通信问题

     wait和sleep区别: 1.wait可以指定时间可以不指定.     sleep必须指定时间. 2.在同步时,对cpu的执行权和锁的处理不同.     wait:释放执行权,释放锁.     ...

  10. java 线程之间通信以及notify与notifyAll区别。

    jvm多个线程间的通信是通过 线程的锁.条件语句.以及wait().notify()/notifyAll组成. 下面来实现一个启用多个线程来循环的输出两个不同的语句. package com.app. ...

随机推荐

  1. Python 提取PowerPoint文档中的图片

    如果你需要在多个PowerPoint演示文稿中使用相同的图片,直接从原始PPT中提取并保存图片可以避免重复寻找和下载.此外,将PPT中的重要图片提取出来可以将其作为备份,以防原文件损坏或丢失.本文将通 ...

  2. 一个.NET开源、快速、功能丰富的跨平台阅读服务器

    前言 今天大姚给大家分享一个基于.NET开源的快速.功能丰富的跨平台阅读服务器,它的设计初衷是提供一个全面的解决方案,满足用户的所有阅读需求.用户可以设置自己的服务器,并与朋友和家人分享阅读收藏:Ka ...

  3. .NET9 - 新功能体验(一)

    被微软形容为"迄今为止最高效.最现代.最安全.最智能.性能最高的.NET版本"--.NET 9已经发布有一周了,今天想和大家一起体验一下新功能. 此次.NET 9在性能.安全性和功 ...

  4. apisix启动报错undefined symbol: EVP_KDF_ctrl, version OPENSSL_1_1_1b

    报错内容 2024/08/06 16:56:13 [error] 154236#154236: *7039 [lua] plugin.lua:110: load_plugin(): failed to ...

  5. after_request 可以直接用于接口日志

  6. Spring开闭原则的表现-BeanPostProcessor的扩展点-1

    上接Spring事务处理时自我调用的解决方案及一些实现方式的风险继续分析,在分析上篇的问题之前,我们需要了解下BeanPostProcessor概念和Spring容器创建Bean的流程. 一.Bean ...

  7. RPM 与 YUM

    RPM 与 YUM rpm 包的管理 rpm 用于互联网下载包的打包及安装工具,它包含在某些 Linux 分发版中.它生成具有.RPM 扩展名的文件.RPM是 RedHat Package Manag ...

  8. 【滑动窗口】codeforces 1290 A. Mind Control

    题意 第一行输入一个正整数 \(T(1 \leq T \leq 1000)\),表示共有 \(T\) 组测试用例.对于每一组测试用例: 第一行输入三个正整数 \(n, m, k(1 \leq m \l ...

  9. 使用 Windows Debugger 调试托管代码

    使用 Windows Debugger 调试托管代码 https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugg ...

  10. 2024年1月Java项目开发指南6:接口测试

    我们使用API Fox这款工具对接口进行测试. (你要是会其他的例如postman进行测试也行) https://apifox.com/ 新建一个项目,新增一个接口 因为这个接口没有参数,所以无需填写 ...