多线程编程中,用于唤醒等待线程的方法有两个,一个是notify()还有一个notifyAll(),
从字面意思来看,前面一个是唤醒等待的线程,后者是唤醒所有的。
其实这是对的,我们还要指出一点的就是notify()如果没有等待的对家,用这个,是不会报错误的,notifyAll()方法也是一样的
/** nofify() 线程使用notify()方法通知那些可能等等该对象的其他线程,如果有多个线程等等该对象,那么线程规划器 任意的挑选出其中一个来发出通知,而其他线程继续保持等待的状态。如果没有任何对象等待该对象,那么notify() 就不会起作用了。在调用notify()方法之前,线程必须获得该对象的对象级别锁,这样就具有排他性了。与 wait()不一样的是,调用notify()不会有临时释放锁,如果调用notify()时,没有持有合适的对象锁,那么 就抛出非法的监视器状态的锁,这个异常是运行时的异常。因此不需要try catch的结构。 如果没有对象的wait()那么就是不起作用的 notifyAll() 这个方法与notify()的工作方式是一样的,但是通知的是等待该对象的线程,而不仅仅通知一个线程 。notifyALL()的优点就是,不用去关心通知的哪个等待的线程,而是简单的通知全部就可以了。缺点就是 如果实际上只有一个线程能够实际器作用,那么这样的通知就是一种浪费。浪费了处理器的资源了。 如果不知道该用notifyALL还是用notify的方法,那么用notifyAll方法还保证用性能来保证程序的安全秩序 **/
下面我们来看下我们的实验:
创建4个线程,都是等待的,需要notify来唤醒他们的。
这个resouces类:
package endual; public class Resources { private String name; public Resources() { this.name = "xx"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void wait1() { synchronized (this.name) { System.out.println("我是wait1,我将进入等待状态"); try { this.name.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("我是wait1,我被唤醒了"); } } public void wait4() { synchronized (this.name) { System.out.println("我是wait4,我将进入等待状态"); try { this.name.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("我是wait4,我被唤醒了"); } } public void wait2() { synchronized (this.name) { System.out.println("我是wait2,我将进入等待状态"); try { this.name.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("我是wait2,我被唤醒了"); } } public void wait3() { synchronized (this.name) { System.out.println("我是wait3,我将进入等待状态"); try { this.name.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("我是wait3,我被唤醒了"); } } public void notify1() { synchronized (this.name) { System.out.println("notify runing") ; name.notify() ; System.out.println("我已经惊醒了一次其他人,不知道是谁啊。。。"); } } }
下面是4个线程:
package endual; public class Threadx1 extends Thread{ private Resources res = null ; public Threadx1(Resources res) { this.res = res ; } public void run() { res.wait1() ; } }
package endual; public class Threadx2 extends Thread{ private Resources res = null ; public Threadx2(Resources res) { this.res = res ; } public void run() { res.wait2() ; } }
package endual; public class Threadx3 extends Thread{ private Resources res = null ; public Threadx3(Resources res) { this.res = res ; } public void run() { res.wait3() ; } }
package endual; public class Threadx4 extends Thread{ private Resources res = null ; public Threadx4(Resources res) { this.res = res ; } public void run() { res.wait4() ; } }
然后用一个唤醒线程来测试 notify和notifyAll的不同
package endual; public class Threadx5 extends Thread{ private Resources res = null ; public Threadx5(Resources res) { this.res = res ; } public void run() { System.out.println("我将等待下,然后执行notify"); try { Thread.sleep(10000) ; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } res.notify1() ; } }
下面是测试的类
package endual; public class CopyOfT { public static void main(String[] args) { Resources res = new Resources(); Threadx1 t1 = new Threadx1(res) ; Threadx2 t2 = new Threadx2(res) ; Threadx3 t3 = new Threadx3(res) ; Threadx4 t4 = new Threadx4(res) ; Threadx5 t5 = new Threadx5(res) ; t1.start() ; t2.start() ; t3.start() ; t4.start() ; t5.start() ; } } /** nofify() 线程使用notify()方法通知那些可能等等该对象的其他线程,如果有多个线程等等该对象,那么线程规划器 任意的挑选出其中一个来发出通知,而其他线程继续保持等待的状态。如果没有任何对象等待该对象,那么notify() 就不会起作用了。在调用notify()方法之前,线程必须获得该对象的对象级别锁,这样就具有排他性了。与 wait()不一样的是,调用notify()不会有临时释放锁,如果调用notify()时,没有持有合适的对象锁,那么 就抛出非法的监视器状态的锁,这个异常是运行时的异常。因此不需要try catch的结构。 如果没有对象的wait()那么就是不起作用的 notifyAll() 这个方法与notify()的工作方式是一样的,但是通知的是等待该对象的线程,而不仅仅通知一个线程 。notifyALL()的优点就是,不用去关心通知的哪个等待的线程,而是简单的通知全部就可以了。缺点就是 如果实际上只有一个线程能够实际器作用,那么这样的通知就是一种浪费。浪费了处理器的资源了。 如果不知道该用notifyALL还是用notify的方法,那么用notifyAll方法还保证用性能来保证程序的安全秩序 **/
下面是测试的结果:
我是wait1,我将进入等待状态
我是wait2,我将进入等待状态
我是wait3,我将进入等待状态
我是wait4,我将进入等待状态
我将等待下,然后执行notify
notify runing
我已经惊醒了一次其他人,不知道是谁啊。。。
我是wait1,我被唤醒了
如果是notify那么唤醒的只有一个
----------------------------------------------------
我们将notify改成notifyAll
public void notify1() { synchronized (this.name) { System.out.println("notify runing") ; name.notifyAll() ; System.out.println("我已经惊醒了一次其他人,不知道是谁啊。。。"); } }
同样的测试:
我将等待下,然后执行notify 我是wait2,我将进入等待状态 我是wait4,我将进入等待状态 notify runing 我已经惊醒了一次其他人,不知道是谁啊。。。 我是wait4,我被唤醒了 我是wait2,我被唤醒了 我是wait3,我被唤醒了 我是wait1,我被唤醒了
全部被唤醒了。这个就是不同点了。通知的全部的等待的对象,而不仅仅是其他一个线程