java-day45
wait notify notifyAll 方法
wait、notify、notifyAll方法都是Object中的方法,任何对象都可以调用到这个方法。
但是只能在加锁的代码块中,使用【当做锁的对象】来调用wait、notify、notifyAll方法。其他情况,如果不是在加锁的代码块中,或者不是使用【当做锁的对象】来调用wait、notify、notifyAll方法,是会报错的。
wait方法:
当一个线程在拿到锁去执行加锁的代码的时候,如果这个线程在代码中执行了【锁对象.wait()】方法,那么这个时候,当前线程就会立马交出cpu使用权,同时释放之前拿到的锁对象,并且从运行状态直接进入到等待池中变为阻塞状态。
当一个线程由于调用了【锁对象.wait()】方法进入到等待池中变为阻塞状态的时候,可以在另一个线程中调用【锁对象.notify()】方法把这个线程叫醒,或者调用这个线程的interrupt方法把它的阻塞状态给打断,这时候在等待池中阻塞的这个线程就会进入到锁池中,并且除以处于阻塞状态,但是它会时刻监控着它需要用的锁是否可用,一旦锁对象变成可用的,那么就会从锁池中的阻塞状态进入到就绪状态。
notify():
唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。
notifyAll():
唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。
多线程例子:
public class ThreadTest7 {
public static void main(String[] args) {
Account account = new Account(5000);
Boy boy = new Boy(account, "tom");
Girl girl1 = new Girl(account, "lily1");
Girl girl2 = new Girl(account, "lily2");
Girl girl3 = new Girl(account, "lily3");
boy.start();
girl1.start();
girl2.start();
girl3.start();
}
private static class Account{
private int balance;
public Account(int balance) {
this.balance = balance;
}
//存钱
public synchronized void pos(int money) {
String name = Thread.currentThread().getName();
balance+=money;
System.out.println(name+"刚刚向账户中存入"+money+"元,当前余额为"+balance+"元");
//钱存好了,马上释放this这个锁了,这里可以叫醒其他线程,让他们从等待池进入到锁池
//这个锁一旦释放,那么就锁池中的线程就会进入到就绪状态,争夺执行权以及获取锁对象,然后再执行代码
this.notifyAll();
}
//取钱
public synchronized void wit(int money) {
String name = Thread.currentThread().getName();
while(balance<money) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
balance-=money;
System.out.println(name+"刚刚从账户中消费"+money+"元,当前余额为"+balance+"元");
}
}
private static class Boy extends Thread{
private Account account;
public Boy(Account account,String name) {
super(name);
this.account = account;
}
@Override
public void run() {
while(true) {
int money = (int)(Math.random()*10000+1);
account.pos(money);//存钱
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class Girl extends Thread{
private Account account;
public Girl(Account account,String name) {
super(name);
this.account = account;
}
@Override
public void run() {
while(true) {
int money = (int)(Math.random()*10000+1);
account.wit(money);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}