• 20.线程间通讯(wait、notify应用)


    线程间通讯(waitnotify应用)

     引言

    线程间如何通讯?通讯的方式其实有好几种,其中有一种就是wait,notify方式,与此相关的,还有一个比较经典的例子,那就是生产者与消费者,生产者指的是生产者线程,消费者指的是消费者线程,生产者线程负责生产数据,消费者线程负责消费数据

    数据还没生产的时候,消费者线程先等待,

     

    与此同时生产者线程开始生产数据,

    数据生产以后叫醒等待中的消费者线程起来消费数据,

    随后生产者线程等待消费者线程开始消费数据,消费完数据以后,叫醒等待中的生产者线程起来生产数据。

     编写一个生产者与消费者的例子

    如此繁复,下面来编写一个生产者与消费者的例子。

    一共有三个步骤,第一步编写一个数据类,第二步编写一个生产者任务,第三步编写一个消费者任务。

     数据类

    首先来编写一个数据类,定义一个描述数据的类data,在类中定义一个存放数据的属性message,随后定义一个获取数据的方法getmessage。再定义一个设置数据的方法。Setmessage。

     生产者

    至此数据类编写完成,再来编写生产者任务,定义一个生产者任务类producer,在类里面定一个data类型的属性,它主要是用于传递数据,然后重载producer构造方法,用于初始化data,接着编写任务部分,定义一个计数器用于给数据编号,方便后面观察使用,while处无限生产数据,定义一个同步锁为data同步代码块,在同步代码块中先判断数据是否为空,当数据为空时开始生产数据,数据生产完以后打印出来,目的是为了和消费数据进行对比,

    生产一个,消费一个,接着调用notify方法唤醒在锁上等待的单个线程。 


    这里唤醒的是消费者线程,再接着使当前现场等待,也就是使生产者线程等待,等消费者线程消费数据,他消费完数据以后会唤醒生产者线程,最后使用try---catch方法抛出的异常,至此生产者任务就全部编写完成。

     消费者

    下面再来编写消费者任务,定义一个消费者任务类consumer,在类中定义一个data属性,它的作用是接收刚刚生产的数据,接着重载consumer构造方法,用于给data初始化使用while(true)无限消费数据,在循环体内定义一个同步锁为data的同步代码块,判断数据是否为空,数据不为空时说明数据已经生产了,但是还没消费。 


    接下来就是消费数据,消费完数据以后,我们要重置数据,还要唤醒生产者线程,接着消费者线程等待,执行生产者任务和消费者任务

    main

    这里我们先将数据创建出来,然后分别创建一个生产者任务和一个消费者任务,将数据分别传递给生产者任务和消费者任务,下面分别创建一个生产者线程和一个消费者线程,将生产者任务传递生产者线程,将消费者任务传递给消费者线程,最后启动这两个线程。

    从执行结果来看,生产者线程和消费者线程节奏非常顺畅,截取一部分结果来看,生产一个数据,消费一个数据,生产一个数据,消费一个数据,

     总结

    最后总结一下本节的内容,本节演示了线程间通讯实例,生产者与消费者利用wait ,notify等待唤醒机制,让线程间友好协作完成任务,更高效的使用资源。 


      

    附录:

    笔记完整文本:

    线程间如何通讯?通讯的方式其实有好几种,其中有一种就是wait裸体反方式,与此相关的,还有一个比较经典的例子,那就是生产者与消费者,生产者指的是生产者线程,消费者指的是消费者形成,生产者县城负责生产数据,消费者县城负责消费数据,数据还没生产的时候,消费者现成先等待,与此同时生产者线程开始生产数据,数据生产以后叫醒等待中的消费者现成起来消费数据,随后生产者线程等待消费者现场开始消费数据,消费完数据以后,交行等待中的生产者线程,其他生产数据如此繁复,下面来编写一个生产者与消费者的例子。 一共有三个步骤,第一步编写一个数据类,第二步编写一个伸展者任务,第三步编写一个消费者任务。首先来编写一个数据类,定义一个描述数据的类data,在类中定义一个存放数据的属性message,随后定义一个获取数据的方法,get message再定义一个设置数据的方法。Set message。这是数据类编写完成再来编写生产者任务,定义一个生产者任务类,producer在另里面定一个data类型的属性,它主要是用于传递数据,然后重载producer构造方法,用于初始化data,接着编写任务部分,定义一个计数器用于给数据编号,方便后面观察使用VR处无限生产数据,定义一个同步所为德操的同步代码块,在同步代码块中先判断数据是否为空,当数据为空时开始生产数据,数据生产完以后打印出来,目的是为了和消费数据进行对比,生产一个消费一个接着调用notify方法唤醒在手上等待的单个线条。 这里唤醒的是消费者现成,再接着使当前现场等待,也就是使生产者线程等待等消费者现成消费数据,他消费完数据以后会唤醒生长者线程,最后使用穿上去捕获胃头方法抛出的异常,至此生产者任务就全部编写完成。下面再来编写消费者任务,定义一个消费者任务类,consumer在类中定义一个贝塔属性,它的作用是接收刚刚生产的数据,接着重载consumer构造方法,用于给德塔初始化使用VR处无限消费数据,在循环体内定义一个同步所谓德塔的同步大板块,判断数据是否为空,数据不为空时说明数据已经生产了,但是还没消费。 接下来就是消费数据,消费完数据以后,我们要重置数据,还要唤醒生产者线程,接着消费者现成的贷执行生产者任务和消费者任务,这里我们先将数据创建出来,然后分别创建一个深战者任务和一个消费者任务,将数据分别传递给圣战者任务和消费者任务,下面分别创建一个圣战的线程和一个消费者现场,将伸展者任务传递给伸展者县城,将消费者任务传递给消费者县城,最后启动这两个线程。从执行结果来看,生产者线程和消费者线程节奏非常顺畅,截取一部分结果来看,生产一个数据,消费一个数据,生产一个数据,消费一个数据,最后总结一下本节的内容,本节演示了县城间通讯实例,生产者与消费者利用wait notify等待唤醒机制,让县城间友好协作完成任务,更高效的使用资源。

     

  • 相关阅读:
    @EnableTransactionManagement的使用
    Spring事务管理之几种方式实现事务
    instr和like的使用区别
    linux查看服务安装目录redis
    struts2的结果类型
    ajax 的 get 方式
    数据库隔离级别
    数据库隔离级别
    input from 表单提交 使用 属性 disabled="disabled" 后台接收不到name="username"的值
    Path Sum
  • 原文地址:https://www.cnblogs.com/cj8357475/p/16086053.html
Copyright © 2020-2023  润新知