java多线程    Java入门    vsftp    ftp    linux配置    centos    FRP教程    HBase    Html5缓存    webp    zabbix    分布式    neo4j图数据库    

Java多线程中的wait与notify,notifyall

  1. java多线程 生产消费者模型 (2014 年 7 月 30 日)
  2. java多线程 优先级 (2014 年 7 月 10 日)
  3. Java多线程,线程守护 (2014 年 7 月 7 日)
  4. Java多线程中的wait与notify,notifyall (2014 年 7 月 5 日)
  5. java 多线程join,合并线程 (2014 年 7 月 4 日)
  6. java多线程,让步yield (2014 年 7 月 2 日)
  7. java多线程休眠 (2014 年 7 月 1 日)
  8. java多线程,同步与锁 (2014 年 6 月 30 日)
  9. java采用Runnable 实现多线线程 (2014 年 6 月 29 日)
  10. java多线程要注意的地方 (2014 年 6 月 28 日)
  11. 认识多任务、多进程、单线程、多线程 (2014 年 6 月 28 日)
  12. java多线程编程全集 (2014 年 6 月 28 日)
  13. 顺序打印,经典java多线程例子 (2014 年 6 月 26 日)
  14. java多线程编程采用Thread继承 (2012 年 7 月 25 日)

在Java多线程编程中,wait()的作用的是让当前线程进入阻塞状态,notify()是让当前线程唤醒继续执行。虽然是对线程状态的控制,但它们其实都是Object中的方法,这是因为wait与notify所起的作用与线程间的互斥锁有关。

在执行wait()和notify()之前,必须要先获得互斥锁,即一定要和synchronized一起使用。wait()的含义是让出获得的互斥锁,并让自己进入阻塞状态。在notify()的时候也已经获得了互斥锁,所做的事情就是唤醒当前线程继续执行。

假如synchronized的锁对象是obj的话,wait和notify正确的使用方法是obj.wait()和obj.notify()。如果使用this作为锁,则可以直接写成wait()和notify()。如果前后使用的锁对象不一致,会发生IllegalMonitorStateException。

当有多个线程共同使用一个互斥锁时,notify()会随机选取一个执行过wait()的线程唤醒,其余会继续保持阻塞状态。如果想唤醒所有阻塞的进程,就使用到了notifyAll()。

有点晕了么,把代码拿去执行可以好好体会下,一会看完代码,看结论

package com.javaer.thread;

public class Twait {

	public static void main(String[] args) {
		 TestThread testThread1 = new TestThread();
	        TestThread testThread2 = new TestThread();
	        TestThread testThread3 = new TestThread();
	        
	        testThread1.start();
	        testThread2.start();
	        testThread3.start();
	        
	        System.out.println("主线程休眠5秒");
	        try {
	            Thread.sleep(1000 * 5);
	        } catch (InterruptedException e) {
	            System.out.println("主线程 Interrupted");
	        }
	        
	        System.out.println("唤醒 线程Thread-0");
	        
	        testThread1.resumeByNotify();
	        
	        try {
	        	System.out.println("主线程再次休眠");
	            Thread.sleep(1000 * 5);
	        } catch (InterruptedException e) {
	            System.out.println("Main Thread Interrupted");
	        }
	        
	        System.out.println("唤醒所有 By NotifyAll");
	        
	        testThread1.resumeByNotifyAll();

	}

}

class TestThread extends Thread {

	private static Object obj = new Object();

	@Override
	public void run() {
		System.out.println(getName() + " 即将进入阻塞");

		synchronized (obj) {
			try {
				obj.wait();
			} catch (InterruptedException e) {
				System.out.println(getName() + " Test Thread Interrupted");
			}
		}

		System.out.println(getName() + " 被唤醒");
	}

	public void resumeByNotify() {
		synchronized (obj) {
			obj.notify();
		}
	}

	public void resumeByNotifyAll() {
		synchronized (obj) {
			obj.notifyAll();
		}
	}
}
Thread-0 即将进入阻塞
Thread-2 即将进入阻塞
主线程休眠5秒
Thread-1 即将进入阻塞
唤醒 线程Thread-0
主线程再次休眠
Thread-0 被唤醒
唤醒所有 By NotifyAll
Thread-1 被唤醒
Thread-2 被唤醒

上面的例子,子线程启动了,就开始阻塞,然后主线程一个个的唤醒。没有线程唤醒,这个子线程将一直等待。

testThread1.resumeByNotifyAll(); 

注释这句话,程序将僵持在那里。传说中的僵尸。

Thread-0 即将进入阻塞
Thread-2 即将进入阻塞
主线程休眠5秒
Thread-1 即将进入阻塞
唤醒 线程Thread-0
主线程再次休眠
Thread-0 被唤醒
唤醒所有 By NotifyAll

到了这里卡住了。

结论
1.wait 当前线程因为某种原因需要进入阻塞状态,即线程暂停
2.notify 唤醒一个阻塞的线程即被wait的
3.notifyall 唤醒所有阻塞线程。

在调用wait的时候,线程自动释放其占有的对象锁,同时不会去申请对象锁。当线程被唤醒的时候,它才再次获得了去获得对象锁的权利。


This entry was posted in WEB前端 and tagged , , , , , , , . Bookmark the permalink.
月小升QQ 2651044202, 技术交流QQ群 178491360
首发地址:月小升博客https://java-er.com/blog/java-wait-notify-notifyall/
无特殊说明,文章均为月小升原创,欢迎转载,转载请注明本文地址,谢谢
您的评论是我写作的动力.

Leave a Reply