java多线程编程基础6-notify()跟notifyALL的区别

java多线程编程基础6-notify()和notifyALL的区别

多线程编程中,用于唤醒等待线程的方法有两个,一个是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,我被唤醒了
 

全部被唤醒了。这个就是不同点了。通知的全部的等待的对象,而不仅仅是其他一个线程