唤醒与等待
notify():随机唤醒一条线程
notifyAll():唤醒全部线程
wait():让线程进入等待状态
补充:
wait和sleep的区别?
sleep:
- 可以设定线程的休眠时间,到点自然醒。
- 如果有锁,那么不释放执行权。
- 如果没有锁,释放执行权。是Thread的一个静态方法。
wait:
- 可以指定休眠时间,也可以不指定。
- 释放锁,并且释放执行权。
- 是Object的一个对象方法。
经典案例:生产者与消费者案例
无限生产与消费,仓库的总量不得超过1000,每次生产的总量+原有仓库的总量不得超过1000,消费的总量不得超过仓库的总量。
【仓库】
class Count {
private int counts; // 用于描述生产总量
private boolean flag; // 用于切换生产与消费状态
public Count(int counts, boolean flag) {
this.counts = counts;
this.flag = flag;
}
public int getCounts() {
return counts;
}
public void setCounts(int counts) {
this.counts = counts;
}
public boolean getFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public String toString() {
return "Count [counts=" + counts + ", flag=" + flag + "]";
}
}
仓库中,主要存放的是原料总量与切换生产者与消费者状态。
【生产者】
class Producer implements Runnable{
private Count c; //仓库总量
public Producer(Count c) {
this.c = c;
}
public Count getC() {
return c;
}
public void setC(Count c) {
this.c = c;
}
@Override
public void run() {
//设置无限循环
while(true){
//设置锁
synchronized (c) {
//当为消费者的线程抢到资源的时候进行休眠
while(c.getFlag()){
try {
c.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//获得最大能生产的总量
int maxCount = 1000 - c.getCounts();
//Math.random()方法产生[0,1)之间的随机数
int newPro = (int) (Math.random()*maxCount);
//设置新的仓库数量
c.setCounts(newPro + c.getCounts());
System.out.println("新生产了" + newPro + "个总量" + ",仓库拥有" + c.getCounts() + "个数量");
//切换状态
c.setFlag(true);
//唤醒全部线程
c.notifyAll();
}
}
}
}
【消费者】
class Consumer implements Runnable{
private Count c; //仓库总量
public Consumer(Count c) {
this.c = c;
}
public Count getC() {
return c;
}
public void setC(Count c) {
this.c = c;
}
@Override
public void run() {
while(true){
synchronized (c) {
//当为生产者的线程抢到资源的时候进行休眠
while(!c.getFlag()){
try {
c.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//获得消费的总量
int newCon = (int) (Math.random()*c.getCounts());
//更新仓库原料
c.setCounts(c.getCounts() - newCon);
System.out.println("新消费了" + newCon + "个总量" + ",仓库拥有" + c.getCounts() + "个数量");
//切换线程状态
c.setFlag(false);
//唤醒全部线程
c.notifyAll();
}
}
}
}
【测试类】
public static void main(String[] args) {
Count c = new Count(1000,true);
new Thread(new Consumer(c)).start();
new Thread(new Producer(c)).start();
new Thread(new Consumer(c)).start();
new Thread(new Producer(c)).start();
}
开了4个线程去测试。