notify()方法、notifyAll()方法和wait()方法 详解

mac2024-05-30  50

线程作为程序内部的多个执行流,相互之间是可以通讯的。线程间通讯可以通过多种方式来进行,例如:线程间可以共享变量来进行通讯,使每个线程根据共享变量的值进行操作和运算,当通过共享变量进行通讯时,通常需要引入同步控制,     线程间也可以通过 wati()、notify()和notifyAll()等方法进行通讯。     每一个类的对象的实例都有一个等待集合,当在该实例上调用wait()方法后,线程都会进入到该实例的等待集合中。     wait()、notify() 和 notifyAll()方法使类Object中定义的方法,由于Java中的类都是Object类的子类,因此,java语言中任何类都可以调用这些方法,但这些方法更多的使在多线程环境中使用。     wait()方法:     wait()方法的调用的一般形式是:     对象名.wait();     称作线程在对象上的等待,作用是把当前的线程放入对象的等待集合中。     wait()方法通常需要放入以synchronized()方法修饰的语句块或方法中,如果在synchronized外部调用wait()方法,运行时刻Java虚拟机会抛出IllegalMonitorStateException异常。     wait()方法通常被放到try{}catch() 语句块中,例如:     try{         wait();     }catch(InterruptedException e){         e.printStackTrace();     }     当线程调用wait()方法后,Java虚拟机会让当前的线程进入到休眠状态,并释放对对象的同步锁的控制权,允许其他线程执行该同步代码,要唤醒该线程,需要在同一个对象上调用notify()或notifyAll()方法。          notify()方法:     线程不能一直在等待集合中,必须有方法对其进行唤醒,notify()方法可以对线程进行唤醒。     notify()方法调用的一般形式如下:     对象名.notify();     当使用当前对象时,使用this作为当前对象的引用,故可以直接写成notify();     当使用某个对象的notify()方法时,将从该对象的等待集合中选择一个等待的线程唤醒,唤醒的线程将从等待集合中删除。

    notifyAll()方法:     notifyAll()方法会将所有在等待集合中的线程唤醒,但由于所有的被唤醒的线程仍然要去争用synchronized锁,而synchronized锁具有排他性,最终只有一个线程获得该锁,进行执行状态,其他线程仍要继续等待。     notifyAll()方法调用一般形似如下:     对象名notifyAll();     当使用当前对象时,使用this作为当前都对象的引用,故可以直接写成notifyAll();     notify() 和notifyAll()方法不需要放入try...catch...语句中,主要的区别是:notify是唤醒一个线程,而notifyAll()是唤醒该对象等待集合中的所有线程。     当只有一个线程等待,另一个线程通知时,建议使用notify(),当有多个线程等待时,建议使用notifyAll()。

    Demo示例:     模拟单缓冲区的生产者和消费者问题。     分析:单缓冲区是指生产者和消费者之间只有一个缓冲区,故生产者生产一个数据后,即进入等待状态,直到消费者消费,消费者消费一个数据后同样进入等待状态,知道生产者生产数据。          //CubbyHole.java  作为一个可操作的对象(共享区域),需要定义 共享变量 和 缓冲区,通过共享变量的值进行操作 缓冲区       public class CubbyHole{         private int goods;         private boolean empty;

        public CubbyHole( ){              empty=true;         }         //从缓冲区取数据         public synchronized int get(){             while(empty){                 try{                     wait();                 }catch(InterruptedException e){                     e.printStackTrace();                 }             }             System.out.println("消费者拿走了物品"+ goods );             empty =true;             //此时唤醒生产者线程,抓紧生产             notify();             return goods;         }         //向缓冲区放入数据         public synchronized void put(int value){             while(!empty){                 try{                       //有产品时,就不需要生产,不需要放数据,线程等待                     wait();                 }catch(InterruptedException e){                     e.printStackTrace();                 }                 }             goods = value;             System.out.println("生产者生产了物品"+goods);             empty=false;             notify();         }         }     //生产者Producer      public class Producer extends Thread{         private CubbyHole cubbyHole;         public Producer(CubbyHole c){             this.cubbyHole =c;         }         public void run(){             for(int i=0;i<50;i++){                 cubbyHole.put((int)(100*Math.random()));             }         }             }     //消费者Consumer     public class Consumer extends Thread{         private CubbyHole cubbyHole;         public Consumer( CubbyHole c){             this.cubbyHole =c;         }         public void run(){             for(int i=0;i<50;i++){                 cubbyHole.get();             }         }         }     //启动类     public class Index{         public static void main(String [] args){             CubbyHole c= new CubbyHole();             Producer  producer = new Producer(c);             producer.start();             Consumer consumer = new Consumer(c);             consumer.start();             }     }

最新回复(0)