多线程之等待唤醒机制

简介

什么叫做等待唤醒机制呢?举一个栗子,请看下图:


当我们开启两条线程时,一条线程专门输入数据,另条取数据。并且要实现,输入一个数据过后,另一方取出一个数据。在多线程的情况下,当输入线程抢到CPU的执行权后,下一次还有可能是输入线程抢到CPU的执行权,就达不到我们想过要的效果。因此,我们需要输入线程执行一次过后,就让它等待,并叫醒输出线程。然后让输出线程执行,执行一次后等待,并且叫醒输入线程。就这样循环往复,就达到了我们想要的效果。

实现步骤

1.创建User类

package Syn;

public class User {
    private String name;
    private String sex;
    private boolean fig;//用来切换线程

    public User() {    }

    public boolean getFig() {     return fig;    }

    public void set(String name ,String sex){
          this.name=name;
          this.sex=sex;
    }
    public String get(){
        return this.name+"  :  "+this.sex;
    }

    public void setFig(boolean fig) {        this.fig = fig;    }
}

这个类帮助我们模拟实现数据的输入输出

2.创建一个输入线程Input类

package Syn;

/**
 * 线程共享数据问题
 */
public class Input implements Runnable{
     private  User user;

    public Input() {    }

    public Input(User user) {//传入User对象
        this.user = user;
    }

    @Override
    public void run() {
           int i=0;
               while (true) {           
                   synchronized (user) {
                       if(user.getFig()) {  //如果已经输入数据 让线程等待
                           try {user.wait();} catch (InterruptedException e) {   }
                       }//为true就让线程等待
                       if (i == 0) {    //每次切换一下  添加不同的数据 方便观察
                           user.set("Rous","woman");
                       } else {
                           user.set("杰克","男");
                       }
                       user.setFig(true);//改为true让输输入线程可以执行 输入线程等待
                       user.notify();//唤醒下一个线程
                       i = (i + 1) % 2;//切换
                   }
               }
    }
}

这一步是等待唤醒机制的核心部分。输入线程第一次进来时fig为false,继续往下执行。set过后,将fig改为true,并且唤醒下一个线程(输出线程)。就算下一次输入线程又抢到了CPU的执行权,判断fig为true则等待。

3.创建一个输出线程Output类

package Syn;

public class Output implements Runnable {
    private User user;

    public Output() {    }

    public Output(User user) {
        this.user = user;
    }

    @Override
    public void run() {
            while (true) {
                synchronized (user) {
                    if(!user.getFig()) {  try { user.wait(); } catch (InterruptedException e) { e.printStackTrace(); }   }
                    System.out.println(user.get());
                    user.setFig(false);
                    user.notify();
                }
        }
    }
}

假如输出线程第一次抢到CPU的执行权,判断fig为false(User对象默认值为false),等待。当输入线程执行一遍后,就会将fig改为true并且唤醒输出线程,此时输出线程才具备执行资格。输出线程执行一遍后,将fig置为false,并唤醒输入线程,以此往复。

4.创建一个测试类

package Syn;

public class Text {
    public static void main(String[] args) {
        User user=new User();

        new Thread(new Input(user)).start();
        new Thread(new Output(user)).start();
    }
}

运行结果:


可以看见输入输出线程是来回切换的。


      每日鸡汤:但行好事,莫问前程!


Over!

猜你喜欢

转载自blog.csdn.net/chianz632/article/details/80093449