线程间通信

Linux双网卡设置IP属于同一网段的ping方法以及现象记录分析 文章目录前言ping以及MAC地址总结 前言 写在前面:经常遇到客户将板卡上的两个网络设备的IP地址设置为同一网段的情况,比如eth0:192.168.0.232,eth1:192.168.0.30. 我的解释是,不能设置为同一网段,或者使用其中一个时候下线另外一个网卡。但是我不知道这个说法到底是根据什么,查了很多资料也没找到明确的说法,但是下面这个实验能够说明一些现象的原因。 ping以及MAC地址 首先查看网卡的信息 ifconfig 因为两个网卡都在同一个网段,所以如果这个时候直接和我们的主机(I 阅读详情

在日常开发中,多线程之间通常会进行相互协作完成任务。为了支持线程间通信,JDK提供了很多很有趣的方法,其中很普遍的就是等待/通知机制。JDK中使用等待wait()方法和通知notify()/notifyAll()实现,这两个方法不是线程内部所有,而是属于Object。

等待/通知机制—第一种方式:

public final void wait() throws InterruptedException

public final native void notify();

实现:wait()方法,顾名思义,就是等待的意思,作用使当前线程在该对象上进行等待,wait()方法时Object类的方法,该方法是当前线程进入该对象的等待队列,并且停止运行,直到其它线程通知或被中断。wait()方法调用之前,线程必须持有该对象的锁,也就是说,只能与sychronized进行配合使用,如果未获取对象级别的锁而调用wait()方法,会抛出IllegalMonitorStateException异常。有等待则必然有通知,与等待wait()方法所对应的,就是notify()方法。当notify()方法被调用时,就会从该对象的等待队列中,随机选择一个线程唤醒,需要注意一点,notify方法在执行之后,并不会立即释放当前对象锁,而是等到sychronized中的语句执行完毕,才会释放对象锁,wait()会立即释放当前锁。除了notify()方法外,还有一个notifyAll()方法也可以唤醒线程,与之不同的是notify()方法只能唤醒一个线程,notifyAll()方法能够唤醒所有的线程。

我们可以用一句话来概括,wait()方法使线程停止运行,notify()使停止的线程继续运行。

为了使大家能够更好的理解,下面给出一段简单的代码:

public static Object lock = new Object();

public static void main(String[] args) throws InterruptedException {
    ThreadA threadA = new ThreadA();
    ThreadB threadB = new ThreadB();
    threadA.start();
    Thread.sleep(100);
    threadB.start();
}

private static class ThreadA extends Thread {
    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("ThreadA wait 开始执行:" + System.currentTimeMillis());
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("ThreadA wait 结束执行:" + System.currentTimeMillis());
        }
    }
}

private static class ThreadB extends Thread {
    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("ThreadB notify 开始执行:" + System.currentTimeMillis());
            lock.notify();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("ThreadB notify 结束执行:" + System.currentTimeMillis());
        }
    }
}

执行结果:

上述代码,我们开启了两个线程,线程A和线程B。线程A,先是获取lock对象的对象锁,然后我们调用了wait()方法,线程A立即停止运行,并且释放了lock的对象锁。线程B,当线程A释放掉lock对象锁之后,线程B获取到锁,然后执行notify()方法,大家从结果可以看到,执行完notify()方法后,线程A并没有立即获取锁开始运行,这是因为,线程B还没有执行完成,2秒之后,线程B执行结束释放lock锁,然后线程A才继续运行。

关于wait()和sleep()方法,这两个方法都可以让线程进行等待,有一点大家注意,那就是wait()方法会立即释放目标对象的对象锁,而sleep()对象不会释放任何资源。

另外,不知道大家有没有发现,在main()方法中,我们加了一句Thread.sleep(100),这一句完全跟业务逻辑不沾边,为什么要加它呢?大家不妨去掉这一句,多执行几次,大家是不是发现,有些时候,线程B先于线程A执行,导致线程A会一直等待。这就是使用wait()和notify()的一个弊端,当notify()先于wait()方法执行,会导致线程永久等待。

在多线程中,大家可能会遇到,也是面试经常遇到的一个问题。线程之间,怎么确保一个线程先于另外一个线程执行完成?

join()小知识点:

在java中,线程提供了一个非常好用的方法join(),使用join()就可以保证线程间的有序执行。

join()部分源码:

关于join()方法,大家只需要记住它可以实现线程间有序执行并且也是依靠等待/通知机制就可以了。至于具体如何实现的,大家可以根据源码描述,就不做过多的介绍了。

上面,我们讲到了使用sychronized和wait()、notify()/notifyAll()方法实现等待/通知机制,那么在灵活的Lock里有没有更加好用的方式呢?

等待/通知机制—第二种方式:

答案是肯定的,Lock类也提供相应的机制,但是需要借助Condition类。Condition类是JDK1.5中才出现的,相对于sychronized的方式,使用它我们可以进行多路通知,也就是选择性通知,从而是线程调度变得更加的灵活。下面我们简单介绍一下Condition的相关方法:

void await() throws InterruptedException;

void signal();

await()相当于之前Object.wait()方法,都是使线程停止运行并且释放锁资源,在使用await()之前必须获得锁。若未加锁使用,则会抛出IllegalMonitorStateException。

signal()方法相当于Object.notify()方法,进行线程通知,使用前也必须获取锁。

我们对sychronized方式的代码进行修改:

private static Lock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
private static class ThreadA extends Thread {
    @Override
    public void run() {
        lock.lock();
        System.out.println("ThreadA await 开始执行:" + System.currentTimeMillis());
        try {
            condition.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        System.out.println("ThreadA await 结束执行:" + System.currentTimeMillis());

    }
}

private static class ThreadB extends Thread {
    @Override
    public void run() {
        lock.lock();
        System.out.println("ThreadB signal 开始执行:" + System.currentTimeMillis());
        condition.signal();
        lock.unlock();
        System.out.println("ThreadB signal 结束执行:" + System.currentTimeMillis());

    }
}

执行结果:

 

 大家可以发现,使用Condition我们也能实现等待/通知机制,对于它的选择性通知是怎么理解法呢?请看:

private static Lock lock = new ReentrantLock();
private static Condition conditionA = lock.newCondition();
private static Condition conditionB = lock.newCondition();

public static void main(String[] args) throws InterruptedException {
    ConditionBDemo conditionBDemo = new ConditionBDemo();
    Thread threadA = new Thread(() -> {
        conditionBDemo.awaitA();
    }

    );
    Thread threadB = new Thread(() -> {
        conditionBDemo.awaitB();
    });
    threadA.start();
    threadB.start();
    Thread.sleep(2000);
    conditionBDemo.signalAll();
}

public void awaitA() {
    lock.lock();
    System.out.println("awaitA 开始执行:" + System.currentTimeMillis());
    try {
        conditionA.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
    System.out.println("awaitA 结束执行:" + System.currentTimeMillis());

}

public void awaitB() {
    lock.lock();
    System.out.println("awaitB 开始执行:" + System.currentTimeMillis());
    try {
        conditionB.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
    System.out.println("awaitB 结束执行:" + System.currentTimeMillis());

}


public void signalAll() {
    lock.lock();
    System.out.println(" signalA 开始执行:" + System.currentTimeMillis());
    try {
        conditionA.signal();
    } finally {
        lock.unlock();
    }
}

执行结果:

       通过程序运行,大家发现,Condition对象一次可以创建多个,这样我们就可以唤醒指定部分的线程,有利于我们控制部分线程行为,这就是选择性唤醒逻辑。

        sychronized方式,被通知的线程是由JVM随机选择的,如果我们需要进行选择性的唤醒线程,大家不妨试试Condition吧!

        关于等待/通知机制,大家应该有所了解了,下面我们介绍线程通信的另外一种方式—线程控制工具。

控制工具类—CountDownLatch:

       CountDownLatch是一个非常好用的多线程控制工具类。它的作用就是用来控制线程等待,让一个线程等待计时结束才开始运行,就好比一个倒计数器。

        CountDownLatch的构造函数接受一个整数,即计数个数。

        public CountDownLatch(int count)

       比如,不知大家看过七龙珠没(龙珠粉,嘿嘿),其中有一个宝物,那就是七颗龙珠,当集齐七颗龙珠的时候(缺一不可),就可以召唤神龙,许三个愿望。我至少有三个愿望,所以我小小的满足了自己:

 

       上面第13行,我们定义了一个CounDownLatch实例,指定计数7,表示当七个线程完成任务,在CountDownLatch上等待的线程才能继续执行。代码第32行,我们使用了countDown()方法,这个方法是用来通知计数器,有一个线程已经完成了任务,应当减一了。代码第22行,我们使用await()方法,这个方法会使当前线程进行等待,当计数完成时,才能继续执行。下面是我们的执行结果:

     在日常开发中,当一个任务需等待其它任务执行完成时,才能继续执行的时候,CountDownLatch值得你拥有。

控制工具类—CyclicBarrier

     CyclicBarrier是另外一种多线程控制工具类。它也是实现线程间计数等待,但相较于CountDownLatch,它更加的复杂和强大。CyclicBarrier意为循环栅栏,栅栏就相当于障碍物,阻止线程继续执行,使线程在栅栏外等待,循环意味着计数器可以多次使       用,当第一次计数完毕后,还可以进行第二次重新计数。

      CyclicBarrier构造函数接受两个参数,parties代表计数总数,当计数完成就会执行barrierAction线程。

      public CyclicBarrier(int parties, Runnable barrierAction)

      比如:大家应该都坐过汽车,在一次坐车事件中,涉及到两个动作,第一次,载满客开车,第二次,到达目的地,乘客全部下车。

      上述21行,我们定义了一个CyclicBarrier类,设定三个乘客。在32行的时候,我们使用了await()方法,让所有线程进行等待,当乘客全部到齐之后,再执行后续的方法。下面是我们的输出结果:

       大家可以看到,执行完成输出了两次,第一次乘客全部上车之后,完成一次计数,会输出执行完成。第二次乘客全部下车的时候,完成一次计数,又会输出一次执行完成。当我们在具体的业务中,可以根据逻辑,在计数完成后添加不同的处理方法。

        CyclicBarrier相交于CountDownLatch,计数可以多次使用,业务范围更加广大。CyclicBarrier的await()方法可能会抛出两个异常,其一就是InterruptedException,其二就是BrokenBarrierException(这是特有的),一旦遇到这个异常,表明CyclicBarrier已经损坏了,线程就会停止运行。

IEC61850规约客户端软件开发实战(第六章) IEC 61850标准中的GOOSE(Generic Object Oriented Substation Event,面向通用对象的变电站事件)功能是变电站自动化系统的核心通信机制,主要用于实现智能电子设备(IED)间高可靠性、低延时的实时信号传输。本章简述其核心功能与技术特点。 阅读详情

相关推荐

5种隐藏代码到图片的实用技巧:从Notepad++到Linux命令全解析

本文详细解析了5种将代码或文本隐藏到图片中的实用数据隐写技巧。从Notepad++尾部追加、Windows命令行合并,到编辑图像元数据、使用十六进制编辑器,再到Linux的cat/dd命令,全面覆盖了从图形界面到命令行的工程化实践方法,帮助开发者和安全研究人员掌握隐蔽信息传输与存储的核心技术。

hh234的博客 353

线程通信的四种方式

多个线程在并发执行的时候,他们在CPU中是随机切换执行的,这个时候我们想多个线程一起来完成一件任务,这个时候我们就需要线程之间的通信了,多个线程一起来完成一个任务,线程通信一般有4种方式: 通过 volatile 关键字 通过 Object类的 wait/notify 方法 通过 condition 的 await/signal 方法 通过 join 的方式 现在有一个问题,两个线程分别打印字符串,但是当线程A每输出两次的时候,线程B就输出一次,如此反复10次。 通过 volatile 关键字 通过

weixin_43786099的博客 3万+

微信聊天记录丢失原因与恢复方案详解

SQLite数据库作为移动应用常见的本地存储方案,其加密机制和存储结构直接影响数据安全性。以微信为例,聊天记录存储在EnMicroMsg.db等SQLite文件中,采用AES加密保护。当手机清理工具误删这些文件时,会导致特定时间段记录丢失。理解数据恢复原理需要掌握文件系统删除机制和闪存特性,其中关键点包括TRIM指令的影响和数据块覆盖风险。通过专业工具如DiskDigger或iMyFone D-Back,配合ADB调试和SQLite数据重组技术,可在黄金时间窗口内恢复记录。日常维护建议结合自动化备份方案和存

weixin_32612263的博客 386

线程间通讯(几种常见的通讯机制,以及实例)

介绍线程间通讯的几种方式,以及一些实例

bigger_belief的博客 1万+

手把手教你用Cadence VPWLF源和参数扫描:搞定非周期激励与gmid曲线绘制(避坑指南)

本文详细介绍了如何在Cadence Virtuoso中使用VPWLF源生成复杂非周期激励信号,并结合gmid方法进行双参数扫描优化电路设计。通过实战案例和避坑指南,帮助工程师高效解决波形生成和参数可视化难题,提升模拟电路设计效率。

weixin_29260291的博客 428

Claude Code教程(二) | Claude Code 核心信息与使用指南

Claude Code 核心信息与使用指南

qq_20236937的博客 2187

线程间的通讯

一.为什么需要线程通讯 线程是操作系统调度的最小单位,有自己的栈空间,可以按照既定的代码逐步的执行,但是如果每个线程间都孤立的运行,那就会造资源浪费。所以在现实中,我们需要这些线程间可以按照指定的规则共同完成一件任务,所以这些线程之间就需要互相协调,这个过程被称为线程的通信。 线程间的通讯定义:多个线程在操作同一份数据时,互相告知自己的状态,避免对同一共享变量的争夺。 二.线程间的通讯方式 线程通讯的方式主要可以分为三种方式,共享内存、消息传递和管道流。 1.共享内存 (1)...

weixin_46060794的博客 3209

【第六届起重机创意大赛国一作品——资料分享】

文章目录前言一、比赛内容分析二、确定方案与作品模型1.方案简图2.作品模型三、电控部分控制思路单片机选择与资源分配拓展板的设计接线与走线代码分享总结

qq_19308801的博客 7783

线程之间的通信方式

前言 我只是个搬运工,尊重原作者的劳动成果,本文来源下列文章链接: https://zhuanlan.zhihu.com/p/129374075 https://blog.youkuaiyun.com/jisuanji12306/article/details/86363390 线程之间为什么要通信? 通信的目的是为了更好的协作,线程无论是交替式执行,还是接力式执行,都需要进行通信告知。首先,要短信线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析: 题目

weixin_41979002的博客 7139

RK3588 DDR5 方案

RK3588 DDR5方案支持多种LPDDR5/LPDDR5X内存型号,包括美光、三星、海力士、江波龙和佰维等品牌。文档详细列出了已验证的DDR5内存规格,涵盖2GB-16GB容量范围,提供组织形式、封装类型和测试状态等信息。其中美光型号最全面,支持12GB/16GB大容量方案。部分型号处于测试验证阶段(T/A),需量产进一步确认性能。该方案为RK3588平台开发提供可靠的内存选型参考。

501846585_QQAndroid_java 1085

【数据集】1970-2023年全球温室气体排放 GHG 数据集 EDGAR

1970-2023年全球温室气体排放 GHG 数据集 EDGAR

WW、forever的博客 1175

鸿蒙中的并发线程间通信、线程间通信对象

并发线程间通信,线程间通信对象、Worker、TaskPool

2301_79624024的博客 1680

Holt-Winters方法预测水电发电量

Holt-Winters 模型, ARMIA,ACF检验 ,Dickey-Fuller 检测,白噪声检测,差分

firefox_yau的博客 1270

线程间通信的几种实现方式

线程间通信的几种实现方式 首先,要短信线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析: 题目:有两个线程A、B,A线程向一个集合里面依次添加元素"abc"字符串,一共添加十次,当添加到第五次的时候,希望B线程能够收到A线程的通知,然后B线程执行相关的业务操作。 方式一:使用 volatile 关键字 基于 volatile...

InterfaceJ的博客 18万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

线程间通信方式

<br />  线程间通信方式 收藏 <br />线程间通信可以通过下列三种方法: <br />1)使用全局变量实现线程间通信 <br />2)使用消息实现线程间通信 <br />3)使用CEvent类实现线程间通信  <br />使用全局变量实现线程间通信: <br />    定义一个全局变量,不同的线程间可以通过修改全局变量的值来进行通信。例如:定义一个控制线程的全局变量 <br />    volatile int  threadController; <br />当 threadControlle

swj2009的专栏 6655

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

iOS线程间通信

什么叫做线程间通信  在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信  线程间通信的体现  1个线程传递数据给另1个线程   在1个线程中执行完特定任务后,转到另1个线程继续执行任务  线程间通信常用方法 1. NSThread :一个线程传递数据给另一个线程 - (void)performSelectorOnMainThread:(SEL)aSelector wi...

LIN1986LIN的专栏 2039

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

线程间通信是什么

线程间通信是什么

weixin_45428910的博客 859

java干货 线程间通信

java干货 线程间通信

qq_51305563的博客 1419

android线程间通信的几种方法_Android线程间通信机制

讲解Handler机制的博文很多,我也看了很多,但说实话,在我对Handler几乎不怎么了解的情况下,每一篇文章我都没太看懂,看完之后脑子里还是充满了疑问。究其原因,是因为几乎每一篇文章一上来就开始深入Handler源码,使得在一些宏观的问题上还是充满疑问,如果你从来没接触过Handler,对一些基础的问题还充满疑问,那深入源码去探究根源肯定会有些吃力。下面,我就从一个初学者思考的角度,来讲一讲H...

weixin_36316291的博客 2046

线程间通信的方式

一、使用volatile关键字 基于volatile关键字来实现线程间相互通信是使用共享内存的思想,就是让这个变量对所有线程都可见,一旦发生变化,都是立即可见的。 public class TestSync { // 定义一个共享变量来实现通信,它需要是volatile修饰,否则线程不能及时感知 static volatile boolean notice = false; ...

qq_41030039的博客 2696

进程间通信、线程间通信

进程间通行(Inter-Process Communication, IPC)和线程间通信(Thread Communication)的方式不完全相同,因为进程和线程的运行环境和特性不同。1、共享变量(Shard Variables)2、消息队列(Message Queue)4、信号量(Semaphore)进程间通信与线程间通信的异同。6、套接字(Socket)进程间通信(IPC)方式。5、信号(Signal)进程间通信、线程间通信。5、事件(Event)6、队列(Queue)1、管道(Pipe)

2401_86968032的博客 1054

RTT线程间的通信

接着上一章讲,这一章讲线程间的通信,常见的有邮箱、信号、消息列队

《愿你归来仍是少年》 992

python中的线程间通信

前面学习了线程的一些基本知识如与进程的区别,线程的组成,线程如何创建等,接下来继续线程的学习。

瑞瑞的博客 3976

c语言线程间传递消息,线程间通信

线程间通信前面一章讲了线程间同步,提到了信号量、互斥量、事件集等概念;本章接着上一章的内容,讲解线程间通信。在裸机编程中,经常会使用全局变量进行功能间的通信,如某些功能可能由于一些操作而改变全局变量的值,另一个功能对此全局变量进行读取,根据读取到的全局变量值执行相应的动作,达到通信协作的目的。RT-Thread 中则提供了更多的工具帮助在不同的线程中间传递信息,本章会详细介绍这些工具。学习完本章,...

weixin_34547628的博客 3758
上一篇: Lock的学习与使用
下一篇: elk(elasticsearch+logstash+kibana)安装入坑
西红柿丶番茄
博客等级 码龄10年 21粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值