(JAVA)-线程中的通信(生产者消费者模型)

发布时间:2023年12月23日

在Java线程通信中,等待通知机制是最传统的方式,就是在一个线程进行了规定操作后,该线程就进入等待状态(wait), 等待其它线程执行完它们的指定代码过后,再将之前等待的线程唤醒(notify)。等待通知机制中使用到wait()、notify()和notifyAll()这三个方法,它们都属于Object这个类中,由于所有的类都从Object继承而来,因此,所有的类都拥有这些共有方法可供使用。而且,由于他们都被声明为final,因此在子类中不能覆写任何一个方法。

1.wait()

该方法只能被锁对象调用,调用能使当前线程跟锁绑定,能够进行后续的唤醒操作。而锁必定从同步方法或同步代码块中获得,因此方法只能写在同步方法或同步代码块内部。使用该方法当前线程进入阻塞状态,同时线程释放锁。直到被唤醒后重新进入就绪状态。

2.notify()

该方法也要在同步方法或同步块中调用,即在调用前,线程也必须要获得该对象的对象锁如果有多个线程等待,则线程规划器任意挑选出其中一个wait()状态的线程来发出通知,而未被选中的对象仍然保持阻塞状态。

注意:当在同步中调用wait()方法时,执行该代码的线程会立即放弃它在对象上的锁。然而在调用notify()时,并不意味着这时线程会放弃该对象锁,而是要等到程序运行完synchronized代码块后,当前线程才会释放锁,wait所在的线程也才可以获取该对象锁。

3.notifyAll()

该方法与notify()方法的工作方式相同,重要的一点差异是:

notifyAll使所有原来在该对象上wait的线程统统退出wait的状态(即全部被唤醒,不再等待notify或notifyAll,但由于此时还没有获取到该对象锁,因此还不能继续往下执行),变成等待获取该对象上的锁,一旦该对象锁被释放(notifyAll线程退出调用了notifyAll的synchronized代码块的时候),他们就会去竞争。如果其中一个线程获得了该对象锁,它就会继续往下执行,在它退出synchronized代码块,释放锁后,其它的已经被唤醒的线程将会继续竞争获取该锁,一直进行下去,直到所有被唤醒的线程都执行完毕。

下面举一个生产者消费者的例子:(生产者) 厨师是一个线程,能够生产拉面,(消费者)顾客是一个线程,能够吃拉面。

我们可以进行简单分析:

厨师(生产者):

判断桌上是否有拉面:1.有(等待)2.没(生产拉面,叫醒消费者)

顾客(消费者)

1.有(开吃)2.没(等待)

public class test {
    public static void main(String[] args) {
        Foodie f=new Foodie();
        Cook c=new Cook();
        f.start();
        c.start();
    }
}

//桌子
 class Desk {
//    查看当前该哪个线程执行
    public static int foodFlag=0;//默认没有
    public static int num=0;
//锁对象
    public static Object lock=new Object();
}


//顾客

 class Foodie extends Thread{
    @Override
    public void run() {
      while(true){synchronized (Desk.lock){
          if(Desk.foodFlag==0){
              try {
                  Desk.lock.wait();//让当前线程跟锁进行绑定
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
          }
          else{
              Desk.num++;
              System.out.println("吃了第"+Desk.num+"碗面条");
              Desk.foodFlag=0;
              Desk.lock.notifyAll();
          }
      }}
    }
}


//厨师
class Cook extends Thread{
    @Override
    public void run() {
        while(true){
            synchronized (Desk.lock){
                if(Desk.foodFlag==1){
                    try {
                        Desk.lock.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }else{
                    Desk.foodFlag=1;
                    System.out.println("做好了一碗面条");
                    Desk.lock.notifyAll();
                }
            }
        }
    }
}

文章来源:https://blog.csdn.net/fdvvg/article/details/135139718
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。