今天小编继续来分享下多线程中的一些内容。

在多线程环境下,由于线程调度的不确定性,所以我们有时候无法很好的去保证其线程的执行顺序。

但是呢,我们又要实现这个顺序执行,所以我们可以使用到这两个方法,wait 和 notify

当然,这两个方法是要在锁内部进行调用的。

那wait 和 notify 方法是什么呢?

wait

是使当前执行代码的线程进行等待。它还具有另一个带参数的版本:wait(long timeout)

这里的等待,会放进一个等待队列中。

然后,接着会释放当前代码锁的资源

当满足一定的条件过后,它会被唤醒,重新去获取锁。

那这里的条件呢,有这些:

1.其他线程进行notify()

2.当带参数的版本中,时间超出了long timeout,也会被唤醒

3.其他线程中,调用本线程的interrupted方法,导致了wait抛出InterruptedException异常

notify

这个方法是唤醒等待的线程。

这里要值得注意的是

1.notify需要在同步方法或者同步块中使用,因为该方法是去通知可能等待该对象的对象锁的其他线程,并使它们重新获取锁资源。

同步方法:是指synchronized关键字修饰的方法。

同步块:

synchronized(锁){

}

2.如若是多个线程进行等待,那么此时唤醒线程,也是随机的,没有所谓的“先来后到之说”

3.notify方法执行完后,不会立即释放当前锁资源,而是还会等到同步方法,或者同步块执行完。

那来看看这个例子,是如何搭配一起使用的吧

 public static void main(String[] args) throws InterruptedException {
        Object obj=new Object();
        Thread t=new Thread(()->{
            synchronized (obj){
                System.out.println("notify之前");
                obj.notify();
                System.out.println("notify之后");
            }
        });
        System.out.println("wait之前");
        synchronized(obj){
            t.start();
            obj.wait();
        }


        System.out.println("wait之后");
    }

代码结果如下:

wait之前

notify之前

notify之后

wait之后

ok,再次引入一个例子,加深对其的了解吧

比如,我现在要按顺序打印A、B、C

那么我们该如何做呢?

我们可以创建三个线程,两个锁

A线程,打印A,B线程中等待,C等待B线程

打印完A,那就唤醒B线程

打印完B线程,然后去唤醒C线程。

代码如下:

public class Demo21 {
    public static Object locker=new Object();
    public static Object locker2=new Object();
    public static void main(String[] args) throws InterruptedException {
        Thread A=new Thread(()->{
            System.out.println("A");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            synchronized (locker){
                locker.notify();
            }
        });
        Thread B=new Thread(()->{
            synchronized (locker){

                try {
                    locker.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("B");
            }
            synchronized (locker2){
                locker2.notify();
            }
        });
        Thread C=new Thread(()->{
            synchronized (locker2){
                try {
                    locker2.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("C");
            }

        });
        A.start();
        B.start();
        C.start();
    }
}

那么,除了这个notify,还有一个notifyAll

那么这个notifyAll又是什么呢?

notifyAll

notifyAll方法可以一次性唤醒所有的线程等待。

这里值得注意的是,notifyAll多次调用是没有问题,不会出现报错

还有,这个是需要同一把锁,才能全部唤醒

唤醒后,所有线程需要重新获取锁,获取锁的过程是系统决定,依然是具有不确定性。

ok,那么小编就先分享到这里吧。

文章作者: 南汐
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 www.phblog.cloud
JavaSE JavaSE
喜欢就支持一下吧