前面多线程的文章中,我们提到了线程状态,有一个状态是WAITING状态,也就是等待状态。
这个状态是指调用了Thread.wait(); 方法后线程失去CPU的执行资格,CPU就算做着随机切换,也不会切换到该线程,只有使用了notify() 方法唤醒了此线程,该线程才能重新获得CPU的执行资格。
而wait() notify() notifyAll() 其实是Object对象的方法,这也就意味着所有对象都有这个方法,而我们等待,唤醒的线程,其实是将其放入了调用此方法对象的后台池子里。
我们来利用一个代码示例来看一下等待唤醒机制。
class Resource{
private boolean mIsProduced = false;
private int count;
public boolean isProduced() {
return mIsProduced;
}
public void setProduced(boolean isProduced) {
this.mIsProduced = isProduced;
}
public void produce() {
count++;
System.out.println("生产者线程 ---> " + Thread.currentThread().getName() + " 生产商品 " + count + "号");
}
public void consume() {
System.out.println("消费者线程 ---> " + Thread.currentThread().getName() + "消费" + count + "商品");
}
}
class Producer extends Thread{
private Resource mResource;
public Producer(Resource resource) {
this.mResource = resource;
}
@Override
public void run() {
while(true) {
synchronized (mResource) {
if(mResource.isProduced()) {
try {
mResource.notify();
mResource.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
mResource.produce();
mResource.setProduced(true);
}
}
}
}
}
class Consumer extends Thread{
private Resource mResource;
public Consumer(Resource resource) {
this.mResource = resource;
}
@Override
public void run() {
while(true) {
synchronized (mResource) {
if(!mResource.isProduced()) {
try {
mResource.notify();
mResource.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
mResource.consume();
mResource.setProduced(false);
}
}
}
}
}
package com.evan.producer_consumer;
public class Demo {
public static void main(String[] args) {
Resource resource = new Resource();
Producer producer = new Producer(resource);
Consumer consumer = new Consumer(resource);
producer.start();
consumer.start();
}
}
我们有一个资源类即 Resource.class
有一个boolean的isProduced,用于记录是否已经生产了商品。还有一个count,记录生产商品的数量。
我们还有两条线程,一条Producer生产者线程,一条Consumer消费者线程。
在Producer的run方法中,有一个死循环,在Synchronized代码块中,我们使用了Resource这个对象作为锁。
当判断到isProduce为false时,我们就直接生产一个商品,当为true时,我们就先通过resource.notify()来唤醒Consumer,然后将自己线程睡眠。
在Consumer的run方法中,当判断到isProduce为true时,我们就直接消费一个商品,当为false时,我们就通过resource.notify*来唤醒Producer,然后将自己睡眠。
这样就利用了等待唤醒机制,来达到效果图上这样的输出效果。
也就是一个线程操作完毕后睡眠自己,但睡眠之前先唤醒对方线程,而这两条线程使用的是同一个锁,而两条线程也都睡眠在同一个锁背后的池子中。