JavaEE(系列7) -- 多线程(wait 和 notify 的使用)

首先对上一章节的指令重排序,在进行解释一下;

假设现在有连个线程 t1 和 t2

t1频繁(速度特别快)读取主内存,效率比较低,就被优化成直接读自己的工作内存。

t2修改了主内存的结果,由于t1没有读主内存,导致修改不能被识别到。

1.什么是主内存,什么是工作内存

        工作内存和主内存都是由英文work memory和main memory翻译来的。所以,工作内存不一定非要是内存,可以是记忆,存储区,不一定是特指“内存条”。

我们平常也会有这样的一组概念 CPU寄存器和内存,那么这两组概念有什么区别?

        其实在很久以前的CPU,上面只有寄存器那个时候我们就可以理解为工作内存就是寄存器,主内存就是内存条,随着时代的进步,现在的CPU上不仅有寄存器,还有了缓存,而且CPU不仅仅有一个缓存,一般都是三级缓存.如下图所示:

         随着缓存的出现,我们就不能说都是在CPU寄存器上读取的数据,此时JVM就引入了一组新的概念,工作内存和主内存.

工作内存准确来说,代表cpu寄存器+缓存(CPU内部存储数据的空间).

  

2.读取的速度:

1.cpu读寄存器速度比读内存快3-4个数量级.

2.缓存读取速度介于寄存器和内存之间。 

        L1最快,空间最小(仍然比寄存器慢)

        L3最慢,空间最大(仍然比内存快很多)

3.CPU读取数据的顺序

        1.先看寄存器里有没有

        2.没有,看L1有没有

        3.没有,看L2有没有

        4.没有,看L3有没有

        5.没有,看内存有没有

具体缓存的大小,对于程序效率的影响,也看实际的应用场景。

下面回归今天的主题👇👇👇👇

目录

1.wait 和notify

2. wait 和 sleep 的对比(面试题)


1.wait 和notify

线程的调度是无序的,随机的。但是,也是有一定的需求场景的,希望线程有序执行。

join是一种控制顺序的方式,但是功效有限。

wait就是让某个线程先暂停下来,等一等。

wait主要做三件事:

1.解锁

2.阻塞等待

3.当收到通知的时候,就唤醒,同时尝试重新获取锁。

注意:

notify就是把该线程唤醒,能够继续执行。

wait和notify是Object的方法

只要你是个类对象(不是内置类型/基本数据类型),都是可以使用wait和notify。

代码讲解:

public class ThreadDemo13 {
    public static void main(String[] args) throws InterruptedException {
        Object locker = new Object();

        Thread t1 = new Thread(()->{

           synchronized(locker){
               try {
                   System.out.println("wait 开始");
                   locker.wait();
                   System.out.println("wait 结束");
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
           System.out.println("2");

        });

        Thread.sleep(1000);

        Thread t2 = new Thread(()->{
            synchronized (locker){
                System.out.println("notify 开始");
                locker.notify();

                System.out.println("notify 结束");
            }
            System.out.println("1");
        });

        t1.start();
        t2.start();
    }
}

 上述代码就是在t1线程里面加了一个wait,在t2线程中加了notify用来唤醒t1线程的wait.

1.使用wait,阻塞等待会让线程进入WAITING状态。wait也提供了一个带参数的版本,参数指定的是最大等待时间。不带参数的wait是死等,带参数的wait就会等最大时间之后,还没有人通知,就自己唤醒自己。

2.唤醒操作,还有一个notifyAll。可以有多个线程堵塞,等待同一个对象唤醒。

3.如果在t1,t2,t3中都调用object.wait。此时在main中调用了object.notify 会随机唤醒上述的一个线程。(另外两个仍然会是waiting状态)

4.wait 结束等待的条件:
1.其他线程调用该对象的 notify 方法.
2.wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).
3.其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常.

总结:

1.wait需要搭配synchronized使用,sleep不需要。

2.wait是Object的方法,sleep是Thread的静态方法。

wait和sleep都是可以提前唤醒的。

他们最大的区别在于初心不同。

wait解决的是线程之间的顺序控制

sleep单纯是让当前线程休眠一会。

2. wait 和 sleep 的对比(面试题)

        其实理论上 wait 和 sleep 完全是没有可比性的,因为一个是用于线程之间的通信的,一个是让线程阻塞一段时间,唯一的相同点就是都可以让线程放弃执行一段时间.

当然为了面试的目的,我们还是总结下:
1. wait 需要搭配 synchronized 使用. sleep 不需要.
2. wait 是 Object 的方法 sleep 是 Thread 的静态方法.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈士奇的奥利奥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值