线程的等待唤醒机制

原创 2015年11月18日 17:52:13

( 1 )等待唤醒机制就是用于解决线程间通信的问题的,使用到的3个方法的含义如下:
wait:告诉当前线程放弃执行权,并放弃监视器(锁)并进入阻塞状态,直到其他线程持有获得执行权,并持有了相同的监视器(锁)并调用notify为止。
notify:唤醒持有同一个监视器(锁)中调用wait的第一个线程,例如,餐馆有空位置后,等候就餐最久的顾客最先入座。注意:被唤醒的线程是进入了可运行状态。等待cpu执行权。
notifyAll:唤醒持有同一监视器中调用wait的所有的线程。


( 2 )调用wait和notify方法需要注意的细节:
wait方法与notify方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法后的线程。
wait方法与notify方法是属于Object类的方法的。因为:锁对象可以是任意对象,而任意对象的所属类都是继承了Object类的。
wait方法与notify方法必须要在同步代码块或者是同步函数中使用。因为:必须要通过锁对象调用这2个方法。

( 3 ) waite和sleep方法的区别
1.相同之处:
线程调用wait()或者是sleep()方法都会进入临时阻塞状态,会释放cpu的执行权。调用时都需要处理 InterruptedException异常。

2.不同之处:
wait(): 释放资源,释放锁。是Object的方法。
sleep():释放资源,不释放锁。是Thread的静态方法

下面通过例子来说明.
/**
 * 要实现的效果就是,有一个水池,水池的容量为50L,一个放水线程,负责放水,每200毫秒放出1L水,当水放完后,通知注水线程工作,同时放水线程停止工作;
 * 注水线程每200毫秒注水1L,水注满时,再通知放水线程继续工作,同时注水线程停止工作.
 * 
 * @author mChenys
 * 
 */
public class _Main5 {
	public static void main(String[] args) {
		Pool pool = new Pool();
		WaterIn in = new WaterIn(pool, "注水线程");
		WaterOut out = new WaterOut(pool, "放水线程");
		in.start();
		out.start();
	}
}

/**
 * 水池,容量为50L
 * 
 * @author mChenys
 * 
 */
class Pool {
	public int MAX_VLAUE = 50;
	public int curr_value = 0;
}

/**
 * 注水线程
 * 
 * @author mChenys
 * 
 */
class WaterIn extends Thread {
	private Pool pool;

	public WaterIn(Pool pool, String name) {
		super(name);
		this.pool = pool;
	}

	@Override
	public void run() {
		while (true) {
			synchronized (pool) {
				try {
					if (pool.curr_value < pool.MAX_VLAUE) {
						// 加水
						Thread.sleep(200);
						pool.curr_value += 1;
						System.out.println(this.getName() + "正在加水,加入 "
								+ pool.curr_value + " L水");
					} else if (pool.curr_value == pool.MAX_VLAUE) {

						System.out.println(this.getName()
								+ "水已加满!!,可以放水了......");
						pool.notify();// 唤醒放水线程
						pool.wait();// 当前线程等待,释放锁对象
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

/**
 * 放水线程
 * 
 * @author mChenys
 * 
 */
class WaterOut extends Thread {
	private Pool pool;

	public WaterOut(Pool pool, String name) {
		super(name);
		this.pool = pool;
	}

	@Override
	public void run() {
		while (true) {
			synchronized (pool) {
				try {
					if (pool.curr_value > 0) {
						// 放水
						Thread.sleep(200);
						pool.curr_value -= 1;
						System.out.println(this.getName() + "开始放水,放出 "
								+ (pool.MAX_VLAUE - pool.curr_value) + " L水");

					} else if (pool.curr_value == 0) {
						System.out.println(this.getName() + "水已放完,可以加水了.....");
						pool.notify();// 唤醒注水线程
						pool.wait();// 当前线程等待,释放锁对象
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

运行效果:
注水线程正在加水,加入 20 L水
注水线程正在加水,加入 40 L水
注水线程正在加水,加入 60 L水
注水线程正在加水,加入 80 L水
注水线程正在加水,加入 100 L水
注水线程正在加水,加入 120 L水
注水线程正在加水,加入 140 L水
注水线程正在加水,加入 160 L水
注水线程正在加水,加入 180 L水
注水线程正在加水,加入 200 L水
注水线程正在加水,加入 220 L水
注水线程正在加水,加入 240 L水
注水线程正在加水,加入 260 L水
注水线程正在加水,加入 280 L水
注水线程正在加水,加入 300 L水
注水线程正在加水,加入 320 L水
注水线程正在加水,加入 340 L水
注水线程正在加水,加入 360 L水
注水线程正在加水,加入 380 L水
注水线程正在加水,加入 400 L水
注水线程正在加水,加入 420 L水
注水线程正在加水,加入 440 L水
注水线程正在加水,加入 460 L水
注水线程正在加水,加入 480 L水
注水线程正在加水,加入 500 L水
注水线程水已加满!!,可以放水了......
放水线程开始放水,放出 20 L水
放水线程开始放水,放出 40 L水
放水线程开始放水,放出 60 L水
放水线程开始放水,放出 80 L水
放水线程开始放水,放出 100 L水
放水线程开始放水,放出 120 L水
放水线程开始放水,放出 140 L水
放水线程开始放水,放出 160 L水
放水线程开始放水,放出 180 L水
放水线程开始放水,放出 200 L水
放水线程开始放水,放出 220 L水
放水线程开始放水,放出 240 L水
放水线程开始放水,放出 260 L水
放水线程开始放水,放出 280 L水
放水线程开始放水,放出 300 L水
放水线程开始放水,放出 320 L水
放水线程开始放水,放出 340 L水
放水线程开始放水,放出 360 L水
放水线程开始放水,放出 380 L水
放水线程开始放水,放出 400 L水
放水线程开始放水,放出 420 L水
放水线程开始放水,放出 440 L水
放水线程开始放水,放出 460 L水
放水线程开始放水,放出 480 L水
放水线程开始放水,放出 500 L水
放水线程水已放完,可以加水了.....
注水线程正在加水,加入 20 L水
注水线程正在加水,加入 40 L水
注水线程正在加水,加入 60 L水
注水线程正在加水,加入 80 L水
注水线程正在加水,加入 100 L水
注水线程正在加水,加入 120 L水
注水线程正在加水,加入 140 L水
注水线程正在加水,加入 160 L水
注水线程正在加水,加入 180 L水
注水线程正在加水,加入 200 L水
注水线程正在加水,加入 220 L水
注水线程正在加水,加入 240 L水
注水线程正在加水,加入 260 L水
注水线程正在加水,加入 280 L水
注水线程正在加水,加入 300 L水
注水线程正在加水,加入 320 L水
注水线程正在加水,加入 340 L水
注水线程正在加水,加入 360 L水
注水线程正在加水,加入 380 L水
注水线程正在加水,加入 400 L水
注水线程正在加水,加入 420 L水
注水线程正在加水,加入 440 L水
注水线程正在加水,加入 460 L水
注水线程正在加水,加入 480 L水
注水线程正在加水,加入 500 L水
注水线程水已加满!!,可以放水了......
放水线程开始放水,放出 20 L水
放水线程开始放水,放出 40 L水
放水线程开始放水,放出 60 L水
放水线程开始放水,放出 80 L水
放水线程开始放水,放出 100 L水
放水线程开始放水,放出 120 L水
放水线程开始放水,放出 140 L水
放水线程开始放水,放出 160 L水
放水线程开始放水,放出 180 L水
放水线程开始放水,放出 200 L水




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

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

从这个图中可以看出,等待状态是一种特殊的状态。使线程陷入等待实际上是暂时剥夺线程当前拥有的CPU时间片和获取CPU时间片的资格,使其返回到就绪状态。除非被唤醒,否则等待时间已满,该线程将一直等待。不会...
  • cuiran
  • cuiran
  • 2011年01月13日 14:24
  • 10984

多线程wait等待和notify唤醒

package com.ibeidou.thread; /**  * 测试wait和notify方法  * 两个线程操作同一对象,一个线程调用wait方法,另一个之后调用notify方法  *...

Java多线程技术初识——8 ,等待唤醒机制(一)

在开始讲解等待唤醒机制之前,有必要搞清一个概念—— 线程之间的通信: 多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等...

线程间的等待唤醒机制-(一)

线程间的同步等待唤醒机制线程的wait()方法使用就是放弃了执行资格 等待的线程都存在线程池当中。 方法:只能在现场同步当中使用。下面的方法必须强调监视器wait();// 可以是当前线程进行等待...

Java线程唤醒与阻塞

阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),学过操作系统的同学对它一 定已经很熟悉了。Java 提供了大量方法来支持阻塞,下面让我们逐一分析。   1. sleep() 方...

线程等待的几种方式

开发过程中经常遇到需要等待某线程结束的情况,目前碰到两种方法,总结下。以后有增加再更新。 1)CountDownLatch CountDownLatch是一个同步辅助类,可以用来等待一个或者几个线程结...

Java主线程等待子线程、线程池

public class TestThread extends Thread { public void run() { System.out.println(this.getName() +...

线程中各种唤醒、等待、睡眠方法之间的区别

一、notify()方法和notifyAll()方法的区别 notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞...

线程中的等待与唤醒

上一篇文章讲到join()方法的时候,用到了一个函数即为yield()方法,它的作用是将cup让与具有相同优先级的线程去使用。本篇文章就为大家讲述线程中的一些关于等待和唤醒的函数。 sleep(): ...

线程通信-等待和唤醒机制和锁(Lock)机制

生产者和消费者案例分析: 经典的生产者和消费者案例(Producer/Consumer):      分析案例:               1):生产者和消费者应该操作共享的资源(实现方式来做...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程的等待唤醒机制
举报原因:
原因补充:

(最多只允许输入30个字)