【线程间通信:等待唤醒机制】

在线程安全解决之后,还是一样存在着如下的问题:

A:如果消费者先抢到CPU的执行权,就会去消费数据,但是现在的数据是默认值,没有意义,应该等着数据有意义,再消费。

B:如果生产者先抢到CPU的执行权,就会去生产数据,但是呢,它生产完数据后,还继续拥有执行权,它又继续产生数据。这是有问题的,它应该等着消费者把数据消费掉,然后再生产。

正常的思路:

A:生产者:先看是否有数据,有就等待,没有就生产,生产完后通知消费者来消费数据。

B:消费者:先是是否有数据,有就消费,没有就等待,通知生产者生产数据。

为了处理这样的问题,JAVA就提供了一种机制,等待唤醒机制。

等待唤醒: Object 类中提供了三个方法:

  wait():等待

  notify():唤醒单个线程

  notifyAll():唤醒所有线程

为什么这些方法不定义在Thread类中呢?

  这些方法的调用必须通过锁对象调用,要所有锁对象都可以调用的话,方法就应该在他们共有的父类上,也就是Object类。

例子:线程间通信:生产者消费者(等待唤醒机制)

package com.test;

public class Student {

    String name;
    int age;
    boolean isTrue;

    public synchronized void set(String name, int age) {
        /**如果有数据,就等待*/
        if (this.isTrue) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        /**设置数据*/
        this.name = name;
        this.age = age;
        /**修改标记*/
        this.isTrue = true;
        this.notify();
    }

    public synchronized void get() {
         /**如果没有数据,就等待*/
        if (!this.isTrue) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
         /**获取数据*/
        System.out.println(this.name + "---" + this.age);
         /**修改标记*/
        this.isTrue = false;
        this.notify();
    }

}
package com.test;

public class SetThread implements Runnable {

    private Student s;
    private int x = 0;

    public SetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {

            if (x % 2 == 0) {
                s.set("叶胖子", 27);
            } else {
                s.set("王瘦子", 31);
            }
            x++;

        }
    }
}
package com.test;

public class GetThread implements Runnable {

    private Student s;

    public GetThread(Student s){
        this.s = s;
    }

    @Override
    public void run() {
        while (true){
            s.get();
        }
    }

}
package com.test;

public class StudentTest {

    public static void main(String[] args) {

        Student s = new Student();

        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s);

        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt);

        t1.start();
        t2.start();

    }

}

原文地址:https://www.cnblogs.com/zuixinxian/p/9574749.html

时间: 2024-10-08 03:14:58

【线程间通信:等待唤醒机制】的相关文章

线程间通信——等待唤醒机制

线程间通信——等待唤醒机制,避免争夺同一资源: 锁对象可以是任意Object类的子类对象: 包子案例: 包子案例——生产者和消费者: 代码实现: 关键就是在于两个线程使用同一个锁对象! 这边是主程序调用这两个线程时候传入的同一个对象! 包子铺线程类——生产者: 其中,baozi类作为成员变量,并且重载了带参的构造方法: 锁对象为调用包子铺带参的构造方法传入的这个包子变量bz; 调用点wait方法必须是锁对象调用,锁对象调用wait方法之后当前线程就进入等待状态,另外一个线程此时应该是正在执行:

JAVA-初步认识-第十四章-线程间通信-等待唤醒机制-代码优化

一. 上一节中的代码写的并不是很眼镜,如下图中的属性,应该都是私有的.我们不应该直接访问资源中的属性,是因为它具备了不安全性. 瞎赋值怎么办呢?为了可控,意味着资源里面的属性需要被私有化,并对外提供方法访问.因此上节中的代码要进行改写. 首先对资源描述类进行修改,至于为什么set方法中写有两个形参,是因为name和sex同时要做赋值,因此直接将它们定义在一起. 而且类中提供了直接输出name和sex的方法,后面的程序中就不需要写那么长的输出语句了.这个输出问题比较简单 关键问题在哪儿呢?如果这么

线程间通讯(等待唤醒机制)

锁.whit(); //将线程丢进线程池,暂停运行. 锁.notify(); //唤醒线程池中的最先存入那个同锁线程 锁.notifyAll(); //唤醒线程池中所有的同锁线程 都使用在同步中,因为要对持有监视器(锁)的线程操作.所以要使用在同步中,因为只有同步才具有锁. 为什么这些操作线程的方法要定义Object类中因为这些方法在操作同步中线程时,都需要标识它们所操作线程持有的锁只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒.不可以对不同锁中的线程进行唤醒. 也就是说,等待和唤

java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)

1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以可以被任意对象调用的方法,定义在Object基类中. wait()方法:对此对象调用wait方法导致本线程放弃对象锁,让线程处于冻结状态,进入等待线程的线程池当中.wait是指已经进入同步锁的线程,让自己暂时让出同步锁,以便使其他正在等待此锁的线程可以进入同步锁并运行,只有其它线程调用notify方

java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

 *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时候才能消费,仓空则等待. *3.当消费者发现仓储没有产品可消费的时候,会唤醒等待生产者生产. *4.生产者在生产出可以消费的产品的时候,应该通知等待的消费者去消费. 下面先介绍个简单的生产者消费者例子:本例只适用于两个线程,一个线程生产,一个线程负责消费. 生产一个资源,就得消费一个资源. 代码如下: pub

线程间的通信--等待唤醒机制

1.多个线程操作相同的资源,但是操作动作不同,所以存在安全问题例如: public class Test { public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r); Output out = new Output(r); Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start();

18、多线程 (线程安全、线程同步、等待唤醒机制、单例设计模式)

线程操作共享数据的安全问题 *A:线程操作共享数据的安全问题 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码. 程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 售票的案例 *A:售票的案例 /* - 多线程并发访问同一个数据资源 - 3个线程,对一个票资源,出售 */ public class ThreadDemo { public static void main(String[] args) { //创建Runnable接口实现

线程组、等待唤醒机制代码优化

线程组:ThreadGroup 把多个线程组合到一起,可以对一批线程进行分类处理,JAVA允许程序直接对线程进行控制 获取线程组:public final ThreadGroup getThreadGroup() 获取线程组的名称:public final String getName() 设置新的线程组:ThreadGroup(String name) 把线程弄到新线程组里:Thread(ThreadGroup group,Runnable target,String name) 等待唤醒机制

Net线程间通信的异步机制

线程间通信 我们看下面的图 我们来看线程间通信的原理:线程(Thread B)和线程(Thread A)通信, 首先线程A 必须实现同步上下文对象(Synchronization Context), 线程B通过调用线程A的同步上下文对象来访问线程A,所有实现都是在同步上下文中完成的.线程B有两种方式来实现线程间的通信. 第一种:调用线程A的同步上下文对象,阻碍当前线程,执行红色箭头调用,直到黄色箭头返回(同步上下文执行完毕)才释放当前线程. (1->2->3->5) 第二种:调用线程A的

多线程-线程间通信

1.多线程-线程间通信-问题演示 多线程间通信:多个线程处理同一资源,但是处理动作却不同. //创建一个资源描述.资源中有name sex.用于存储数据. class Resource{     String name;     String sex; } //需要定义一个输入任务描述.既然是线程任务,必须实现Runnable接口.  class Input implements Runnable{     private Resource r;     Input(Resource r){