线程的等待与唤醒
-
(1)多个线程可以竞争,也可以协作
卖票属于竞争
消费与生产属于协作
吃货每吃完一个包子,那么就要告诉包子铺生成包子
包子铺每生产一个包子,就要通知吃货去吃
-
(2)相关方法
void wait():让当前线程等待,如果没有人唤醒他,就一直等
void wait(long timeout):让当前线程等待,如果到了指定的毫秒值还没有人唤醒他就自己醒
void notify() 唤醒一个线程,唤醒的是当前对象锁下的一个线程
void notifyAll() 唤醒所有线程,唤醒的是当前对象锁下面的所有线程
这些方法一定要放在同步代码块中去使用,并且这些方法要通过锁对象去调用
等待唤醒机制的代码实现

//仓库
class CangKu { //当作 锁对象
//定义一个变量体现数量
public int productNum = 0;
}
//生产方
class ProductTask implements Runnable {
private CangKu cangKu; //共用一个仓库不能自己创建,由外部传入
public ProductTask(CangKu cangKu) {
this.cangKu = cangKu;
}
@Override
public void run() {
while (true) {
//通知与等待必须写在同步代码块中
synchronized (this.cangKu)/*判断是否有锁可用*/ {/*有就进入*/
if (this.cangKu.productNum == 0) {
++ this.cangKu.productNum;
System.out.println("生产了一个产品 " + this.cangKu.productNum);
//通知消费者
this.cangKu.notify();
} else {
//有货不用生产,等待通知
try {
System.out.println("生产方等待中.");
this.cangKu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}//end if
}//end synchronized 出房间释放锁
}
}
}
//消费方
class ConsumerTask implements Runnable {
private CangKu cangKu;
public ConsumerTask(CangKu cangKu) {
this.cangKu = cangKu;
}
@Override
public void run() {
while (true) {
synchronized (this.cangKu) {
//判断 是否为0
if (this.cangKu.productNum == 0) {
try {
System.out.println("消费方等待中.");
this.cangKu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//有货可以吃
-- this.cangKu.productNum ;
System.out.println("消费了一个产品:" + this.cangKu.productNum);
//通知生产
this.cangKu.notify();
}//end if
}//end synchronized
}
}
}
public class Demo10 {
public static void main(String[] args) {
//任务对象
CangKu cangKu = new CangKu();
ProductTask productTask = new ProductTask(cangKu);
ConsumerTask consumerTask = new ConsumerTask(cangKu);
//定义线程
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(productTask);//生产
pool.submit(consumerTask);//消费
}
}
//1:逻辑要正确
//2: notify wait写在同步代码块中,使用同一个对象 仓库
//3: this.cangku.wait() this.wait() 前一个使用的是仓库对象 ,后一个使用的是任务对象