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

Posted zuixinxian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程间通信:等待唤醒机制相关的知识,希望对你有一定的参考价值。

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

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();

    }

}

 

以上是关于线程间通信:等待唤醒机制的主要内容,如果未能解决你的问题,请参考以下文章

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

等待与唤醒机制

等待与唤醒机制(线程之间的通信)

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

等待唤醒机制

线程系列三线程的等待与唤醒机制