文章出自:http://blog.youkuaiyun.com/cuiran/article/details/6133745
从这个图中可以看出,等待状态是一种特殊的状态。使线程陷入等待实际上是暂时剥夺线程当前拥有的CPU时间片和获取CPU时间片的资格,使其返回到就绪状态。除非被唤醒,否则等待时间已满,该线程将一直等待。不会被JVM线程调度器选中并赋予CPU时间片。处于等待的线程一旦恢复执行,与其他处于就绪状态被线程调度器选中的线程不同,将从上次结束执行的断点处开始执行,而非从头开始。
使线程中断运行,返回就绪状态的手段是调用java.lang.Object对象的wait()方法;唤醒处于等待状态的线程的手段是调用java.lang.Object对象的notify()方法
为了加深理解,下面就通过具体例子来说明线程等待和唤醒
第一个:
通过继承Thread来创建子线程。
- /**
- * NotifyWaitingThread.java
- * 版权所有(C) 2011 cuiran2001@163.com
- * 创建:崔冉 2011-1-11 上午11:24:33
- */
- package com.cayden.thread;
- /**
- * @author 崔冉
- * @version 1.0.0
- * @desc
- */
- public class NotifyWaitingThread {
- /**
- * @param args
- */
- public static void main(String[] args) throws InterruptedException{
- // TODO Auto-generated method stub
- MyThread [] threads=new MyThread[3];
- for(int i=0;i<3;i++){
- threads[i]=new MyThread();
- threads[i].no=i;
- threads[i].setDaemon(true);
- threads[i].start();
- }
- Thread.sleep(5000);
- for(int i=0;i<3;i++){
- synchronized(threads[i]){
- threads[i].notify();
- }
- }
- }
- }
- class MyThread extends Thread{
- public int no=0;
- public void run(){
- System.out.println("第"+this.no+"个线程开始等待5分钟");
- try{
- synchronized(this){
- this.wait(5*60*1000);
- }
- }catch (InterruptedException e) {
- // TODO: handle exception
- e.printStackTrace();
- }
- System.out.println("第"+this.no+"个线程被唤醒");
- }
- }
运行效果如下:
- 第0个线程开始等待5分钟
- 第2个线程开始等待5分钟
- 第1个线程开始等待5分钟
- 第0个线程被唤醒
- 第2个线程被唤醒
- 第1个线程被唤醒
第二个:
通过实现Runnable接口来创建子线程
- /**
- * NotifyWaitingThreadWithRunnable.java
- * 版权所有(C) 2011 cuiran2001@163.com
- * 创建:崔冉 2011-1-11 下午01:48:04
- */
- package com.cayden.thread;
- /**
- * @author 崔冉
- * @version 1.0.0
- * @desc
- */
- public class NotifyWaitingThreadWithRunnable {
- /**
- * @param args
- */
- public static void main(String[] args) throws InterruptedException{
- // TODO Auto-generated method stub
- Runner[] runners=new Runner[3];
- Thread[] threads=new Thread[3];
- for(int i=0;i<3;i++){
- runners[i]=new Runner(i);
- threads[i]=new Thread(runners[i]);
- threads[i].setDaemon(true);
- threads[i].start();
- }
- Thread.sleep(500);
- for(int i=0;i<3;i++){
- synchronized (runners[i]) {
- runners[i].notify();
- }
- }
- }
- }
- class Runner implements Runnable{
- private int no=0;
- public Runner(int no){
- this.no=no;
- }
- @Override
- public void run() {
- // TODO Auto-generated method stub
- System.out.println("第"+this.no+"个线程开始等待5分钟");
- try{
- synchronized(this){
- this.wait(5*60*1000);
- }
- }catch (InterruptedException e) {
- // TODO: handle exception
- e.printStackTrace();
- }
- System.out.println("第"+this.no+"个线程被唤醒");
- }
- }
运行效果如下:
- 第0个线程开始等待5分钟
- 第2个线程开始等待5分钟
- 第1个线程开始等待5分钟
- 第1个线程被唤醒
- 第0个线程被唤醒
- 第2个线程被唤醒
第三个:
通过实现Runnable,又通过Object对象的notifyAll()方法一次性唤醒多个同一个对象创造的线程。
- /**
- * NotifyWaitingThreadWithSameRunnable.java
- * 版权所有(C) 2011 cuiran2001@163.com
- * 创建:崔冉 2011-1-11 下午02:34:01
- */
- package com.cayden.thread;
- /**
- * @author 崔冉
- * @version 1.0.0
- * @desc
- */
- public class NotifyWaitingThreadWithSameRunnable {
- /**
- * @param args
- */
- public static void main(String[] args) throws InterruptedException{
- // TODO Auto-generated method stub
- SameRunner runner=new SameRunner();
- Thread[] threads=new Thread[3];
- for(int i=0;i<3;i++){
- threads[i]=new Thread(runner);
- threads[i].setDaemon(true);
- threads[i].start();
- }
- Thread.sleep(500);
- synchronized(runner){
- runner.notifyAll();
- // runner.notify(); //被唤醒的只有一个线程
- }
- }
- }
- class SameRunner implements Runnable{
- @Override
- public void run() {
- // TODO Auto-generated method stub
- System.out.println("线程开始等待5分钟");
- try{
- synchronized(this){
- this.wait(5*60*1000);
- }
- }catch (InterruptedException e) {
- // TODO: handle exception
- e.printStackTrace();
- }
- System.out.println("线程被唤醒");
- }
- }
运行效果如下:
- 线程开始等待5分钟
- 线程开始等待5分钟
- 线程开始等待5分钟
- 线程被唤醒
- 线程被唤醒
- 线程被唤醒
总结:1).利用Thread.sleep().使线程开始休眠指定的时间,以便让各个子线程进入等待状态。
2).synchronized同步锁的使用。这一块在后面文章中会加以解说。