线程的等待唤醒机制

( 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水

 

 
以下是一个简单的线程等待唤醒机制的示例,其中包括一个生产者和一个消费者线程: ```java public class WaitNotifyExample { public static void main(String[] args) { final Object lock = new Object(); final List<Integer> list = new ArrayList<>(); Thread producer = new Thread(() -> { synchronized (lock) { for (int i = 0; i < 10; i++) { list.add(i); System.out.println("Produced: " + i); lock.notify(); // 唤醒等待线程 try { lock.wait(); // 等待消费者线程唤醒 } catch (InterruptedException e) { e.printStackTrace(); } } } }); Thread consumer = new Thread(() -> { synchronized (lock) { while (list.isEmpty()) { try { lock.wait(); // 等待生产者线程唤醒 } catch (InterruptedException e) { e.printStackTrace(); } } for (int i = 0; i < list.size(); i++) { System.out.println("Consumed: " + list.get(i)); } list.clear(); lock.notify(); // 唤醒等待线程 } }); producer.start(); consumer.start(); } } ``` 生产者线程通过`synchronized`关键字获取锁,然后在循环中生产数据并将其添加到列表中,然后使用`notify()`方法唤醒等待线程,并使用`wait()`方法等待消费者线程唤醒。消费者线程也使用`synchronized`关键字获取锁,并在循环中等待列表中有数据。一旦列表中有数据,它将消费这些数据,清空列表,并使用`notify()`方法唤醒等待线程。由于`synchronized`关键字在获取锁后自动释放锁,因此在等待期间,其他线程可以访问共享资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值