第二部分 线程的等待和唤醒

从这个图中可以看出,等待状态是一种特殊的状态。使线程陷入等待实际上是暂时剥夺线程当前拥有的CPU时间片和获取CPU时间片的资格,使其返回到就绪状态。除非被唤醒,否则等待时间已满,该线程将一直等待。不会被JVM线程调度器选中并赋予CPU时间片。处于等待的线程一旦恢复执行,与其他处于就绪状态被线程调度器选中的线程不同,将从上次结束执行的断点处开始执行,而非从头开始。

 使线程中断运行,返回就绪状态的手段是调用java.lang.Object对象的wait()方法;唤醒处于等待状态的线程的手段是调用java.lang.Object对象的notify()方法

为了加深理解,下面就通过具体例子来说明线程等待和唤醒

第一个:

通过继承Thread来创建子线程。

/** * NotifyWaitingThread.java * 版权所有(C) 2011 [email protected] * 创建:崔冉 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 [email protected] * 创建:崔冉 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 [email protected] * 创建:崔冉 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同步锁的使用。这一块在后面文章中会加以解说。

你可能感兴趣的:(jvm,thread,c,String,object,Class)