1.notify
public final void notify()唤醒正在等待对象监视器的单个线程。 如果任何线程正在等待这个对象,其中一个被选择被唤醒。 选择是任意的,并且由实施的判断发生。 线程通过调用
wait
方法之一等待对象的监视器。唤醒的线程将无法继续,直到当前线程放弃此对象上的锁定为止。 唤醒的线程将以通常的方式与任何其他线程竞争,这些线程可能正在积极地竞争在该对象上进行同步; 例如,唤醒的线程在下一个锁定该对象的线程中没有可靠的权限或缺点。
注意:该方法只能由作为该对象的监视器的所有者的线程调用
2.wait
public final void wait() throws InterruptedException导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。 换句话说,这个方法的行为就好像简单地执行呼叫
wait(0)
。当前的线程必须拥有该对象的显示器。 该线程释放此监视器的所有权,并等待另一个线程通知等待该对象监视器的线程通过调用
notify
方法或notifyAll
方法notifyAll
。 然后线程等待,直到它可以重新获得监视器的所有权并恢复执行。
package com.xcl_O;
import java.util.Calendar;
/**
* 3. 银行存取款
* 要求:
* 小明打算去提款机上取钱, 发现卡上没有钱,这时候他告知妈妈去存钱,妈妈存了钱了,告知小明存好了可以取钱了。
* 小明分多次取钱,每次取100,当发现钱不够100,就等妈妈存钱
* 妈妈每次存钱2000,当发现钱小于100就存钱,并且通知小明取取钱,当大于100就等小明钱不够再存
*/
class B {//先造一个对象来作为桥梁(让两个线程都可以使用次对象以便达到操作统一对象)
private String name;//没得用
private Boolean Cun;//为了判断是否先要钱还是先存钱
private int money;//初始化值
public Boolean getCun() {
return Cun;
}
public Boolean isCun() {
return Cun;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setCun(Boolean cun) {
Cun = cun;
}
public B(String name) {
this.name = name;
}
public B(String name, Boolean cun, int money) {//构造函数就是为了传参
this.name = name;
Cun = cun;
this.money = money;
}
@Override
public String toString() {
return "B{" + "name='" + name + '\'' + ", Cun=" + Cun + ", money=" + money + '}';
}
}
class Son implements Runnable{
private B b;
public Son(B b) {
this.b = b;
}
@Override
public void run() {
while (true) {//死循环
synchronized (b) {//为了锁对象来进行进入的对象保持一致性
if (! b.isCun()){//如果为false 则进入程序
if (b.getMoney()>= 100){//判断钱数是否是小于100 如果不是小于100 则进入大廓号的语句
b.setMoney(b.getMoney()-100);
System.out.println(Thread.currentThread().getName() +"取了100元" +", 还剩:" +b.getMoney()+"元。 取款日期为:"+Calendar.getInstance().getTime());
//获取当前线程对象sout的名字和金钱信息等等。。。
}else {
b.setCun(true);//如果金钱数小于一百元则执行该语句 然后将Cun属性赋值为true
// 然后唤醒妈妈然后昂妈妈存钱
b.notify();
}
}else {
try {
b.wait();//等待着被唤醒让妈妈线程先执行,妈妈存完钱之后就会唤醒我
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class Monther implements Runnable{
private B b;//将类对象作为一个属性
public Monther(B b) {//为了传参数
this.b = b;
}
@Override
public void run() {
while (true){//死循环
synchronized (b) {//锁是为了保证对象的一致性
if (b.isCun()){//如果为true则执行该语句
if (b.getMoney() < 100){//当钱数小于100时 执行下面语句
b.setMoney(2000);//需要给儿子增加2000元
System.out.println(Thread.currentThread().getName()+"已经存上"+b.getMoney()+"元");
}else {
b.setCun(false);//将二千元存进去之后 就来将CUN 变为false 然后
b.notify();//就要唤醒儿子 让儿子去花钱
try {
Thread.sleep(1000);//为了省钱就去将时间设为1秒钟
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}else {
try {//然后就等待被唤醒(儿子花完钱就会唤醒我)这是等待的时间就是儿子花钱的时间
b.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public class Demo1 {
public static void main(String[] args) {
B b = new B("小明",true,500);//先new一个对象来作为桥梁
Son son = new Son(b);//儿子对象
Thread thread = new Thread(son,"小明");//儿子线程
thread.start();//启动儿子线程
Monther monther = new Monther(b);//new 一个妈妈对象
Thread thread1 = new Thread(monther,"妈妈");//妈妈线程
thread1.start();//启动妈妈线程
}
}