人工智能学习

wait、notify和notifyAll方法学习

本文主要是介绍wait、notify和notifyAll方法学习,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

wait、notify和notifyAll方法

wait() 方法会使该锁资源释放,然后线程进入等待WAITING状态,进入锁的waitset中,然后等待其他线程对锁资源调用notify方法或notifyAll方法进行唤醒,否则就会进入无限等待。唤醒后会继续执行wait() 后面的代码。

wait(long timeout)wait(long timeout, int nanos) 两个方法差不多,就是对wait方法的过期时间进行限制,如果超过该时间,就将线程放出来进入等待队列继续请求锁资源,然后得到锁资源后继续从wait()方法后面执行。等待过程中线程的状态为TIMED_WAITING,和wait()方法进行区分。

wait和sleep方法进行对比

wait方法首先会释放锁,然后进入一个WAITING(没有timeout参数)或者TIMED_WAITING(有timeout参数)状态,然后等待唤醒或者过期自动唤醒,重新去竞争锁资源。

sleep方法就不会释放锁资源,直接将线程设置进入TIMED_WAITING状态,等待时间过去继续执行后续代码

设计模式-保护性暂停

A ---- > B <------- C

首先会两个线程需要对一个GuardObject 进行存取,首先A会等待C把东西放进去然后A将其取出。

class GuardObjectOld{
    private Object value;

    public synchronized Object getObject(){
        while (value == null){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return value;
    }

    public synchronized void setObject(Object o){
        this.value = o;
        this.notifyAll();
    }
}

首先呢两个线程会对同一个GuardObject 对象进行存取。

取线程会调用getObject()方法,然后当value为空会进入wait方法等待存线程放入资源。

存线程调用setObject方法放入资源,然后进行通知waitset中的线程醒过来取资源。

然后可以对其进行增加超时保护

/**
 * 增加超时检验
 */
@Slf4j
class GuardObject{
    private Object value;

    public synchronized Object getObject(long timeout){
        long startTime = System.currentTimeMillis();
        long waitTime = 0;
        while (value == null){
            if (timeout - waitTime <= 0){
                break;
            }
            try {
                // 防止虚假唤醒,然后又要等好几秒
                this.wait(timeout - waitTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            waitTime = System.currentTimeMillis() - startTime;
        }
        return value;
    }

    public synchronized void setObject(Object o){
        this.value = o;
        this.notifyAll();
    }
}

在上述代码基础上加入了超时保护,首先是记录运行时间waitTime,刚开始为0。

如果过程中没有被其他的线程唤醒,线程会执行wait(2000)方法等待2秒如果没有被唤醒就直接继续执行下面代码,继续循环if语句判断true跳出循环。

如果过程中被其他的线程虚假唤醒了,然后线程就会发现资源还是空,然后会继续循环,等待时间就是设定的timeout时间减去已经等待的时间waittime。

这篇关于wait、notify和notifyAll方法学习的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!