当前位置: 首页 > news >正文

仙居住房和城乡建设规划局网站百度竞价价格

仙居住房和城乡建设规划局网站,百度竞价价格,免备案的网站空间,高唐做创建网站的公司前言 本篇介绍的是wait与notify方法,通过wait来顺序控制执行一些代码,了解单例模式,进行单例模式的简单实现,介绍饿汉模式下出现线程不安全的问题与解决;如有错误,请在评论区指正,让我们一起交…

前言

本篇介绍的是wait与notify方法,通过wait来顺序控制执行一些代码,了解单例模式,进行单例模式的简单实现,介绍饿汉模式下出现线程不安全的问题与解决;如有错误,请在评论区指正,让我们一起交流,共同进步!


文章目录

  • 前言
  • 1. 认识 wait 与 notify
    • 1.1 wait,notify的使用
    • 1.2 使用 wait 必须加锁
    • 1.3 notify 也需要加锁
    • 1.4 wait 与 sleep 的区别?
  • 2.单例模式
    • 2.1 单例模式的介绍
    • 2.2 java语法中如何实现单例模式
    • 2.3 实现单例模式
      • 2.3.1 饿汉模式实现单例
      • 2.3.2 懒汉模式实现单例模式
      • 2.3.3 懒汉模式下产生的线程不安全
        • 2.3.4 小结懒汉模式下产生的线程不安全
  • 总结

本文开始

1. 认识 wait 与 notify

为什么要有wait 与 notify ?
线程调度是无序的,但是一定场景下,希望线程是有序执行的,这就可以使用wait 和 notify;

之前了解了,join能够等待,来控制顺序,但是其功效有限;而wait也是等待的作用,但又不相同;

1.1 wait,notify的使用

wait: 发现条件不满足 / 时机不成熟,就会阻塞等待;
notify: 其他线程构造了一个成熟的条件,就可以唤醒等待线程;

例如:
A去ATM取钱,A进去取钱,发现ATM中没有钱,A就会wait释放锁并阻塞等待,当另外的线程,把ATM冲上钱,就可以唤醒A,让A进行取钱操作;

wait与notify前提使用条件:
wait 和 notify 是Object 方法,只要是类对象,就可以使用wait,notify;

1.2 使用 wait 必须加锁

不加锁代码:

    public static void main(String[] args) throws InterruptedException {Object object = new Object();object.wait();//中断就会报异常}

结果报错:

在这里插入图片描述

【注】illegal Monitor State Exception: 非法的,监视器(synchronized: 监视器锁),状态,异常;=》非法的锁状态异常;

object.wait() : wait方法做三件事
① 解锁: 这就说明,使用wait必须加锁(必须写的synchronized代码块中),才能解锁;
【注】加锁对象必须和wait的对象是同一个
② 阻塞等待
③ 当收到通知的时候,就唤醒,同时尝试重新获取锁;

join 与 wait 的区别:
前提有两个线程t1,t2;
① join等待一定是串行的,只能t2先执行完,再继续执行t1;
② wait和notify, 中的wait只是等待线程中的一部分;可以先让t2执行完一部分,再执行t1, t1执行一部分,t2再继续执行;(可以调整执行的顺序)

wait 使用的两种方式
使用wait会阻塞等待让线程进入WAITING状态;
带参数 的wait(时间):带参数的,指最大等待时间;(等到最大时间,没人通知,就会自己唤醒自己)
不带参数 的wait : 会一直等待;(只能等待被唤醒或者被中断)

1.3 notify 也需要加锁

前提:必须先执行wait, 然后才能有notify; (不然没锁,怎么解锁) 虽然没有唤醒wait,但是不会让代码出现异常;

notifyAll : 唤醒多个线程;
【注】如果有多个线程调用wait,notify只能随机唤醒一个;而notifyAll 可以把线程全部唤醒,此时多个线程重新竞争锁,再依次执行;

1.4 wait 与 sleep 的区别?

① wait用于线程通信,sleep用于阻塞线程;
② 设计的初心不同,wait解决线程之间顺序控制;sleep只能让当前线程休眠一会;
③ wait 是Object的方法,sleep是Thread的静态方法;
④ wait使用需要配合synchronized使用,sleep不需要;

2.单例模式

什么是单例模式?
单例模式,是一种经典的设计模式;类似于玩游戏的攻略 / 下棋的棋谱 ,有一些固定的招式;

2.1 单例模式的介绍

单例:指单个实例,一个程序中,某个类,只能创建出一个实例(对象),不能创建多个对象;

java中的单例模式,借助java语法,保证某个类,只能创建出一个实例,而不能new多次;

2.2 java语法中如何实现单例模式

这里介绍两种方式:
饿汉模式
从容的状态:比如吃饭洗碗,吃完饭马上洗碗;
懒汉模式
急迫的状态:比如吃饭洗碗,吃完饭,先不着急洗碗,等下一次用的再洗碗;

例如计算机读取硬盘中的文件内容,并显示;
饿汉:把文件所有内容全部读到内存中,并显示;
懒汉:只读取文件中的一部分,能填充当前屏幕,如果翻页,再读取其他文件内容,如果不翻页,就不用再读;

2.3 实现单例模式

此处把Singleton设置为单例的

2.3.1 饿汉模式实现单例

饿汉模式:开始直接创建实例,不管用不用;
【注】
① 唯一实例本体使用static修饰
② 获取实例方法提供get方法
③ 禁止外部再创建实例 使用private修饰无参构造(private修饰必须提供get方法来获取实例)

class Singleton {//唯一实例本体private static Singleton instance = new Singleton();//被static修饰,该属性是类的属性 =》 类对象//JVM 中,每个类的类对象只有唯一一份,类对象的成员也是唯一一份//private修饰,需要get方法,外部才能获取到//获取到实例的方法public static Singleton getInstance() {return instance;}//禁止外部new 实例private Singleton() {}
}

测试代码:

 public static void main(String[] args) {//此时singleton1,singleton2调用的是同一个对象Singleton singleton1 = Singleton.getInstance();Singleton singleton2 = Singleton.getInstance();//为了防止new一个新的对象,给无参构造用private修饰//Singleton singleton3 = new Singleton();//此时不能new了}

2.3.2 懒汉模式实现单例模式

懒汉模式:开始不创建实例,等到使用的时候才会创建;

class SingletonLazy {//不马上创建实例private static SingletonLazy instance = null;public static SingletonLazy getInstance() {//等到调用的时候,才创建实例if(instance == null) {instance = new SingletonLazy();}//如果有了实例直接返回,也保证了只要一个实例return instance;}private SingletonLazy() {}
}

测试:

    public static void main(String[] args) {SingletonLazy singletonLazy1 = SingletonLazy.getInstance();SingletonLazy singletonLazy2 = SingletonLazy.getInstance();//比较singletonLazy1 == singletonLazy2,相等就是同一个对象System.out.println(singletonLazy1 == singletonLazy2);}

2.3.3 懒汉模式下产生的线程不安全

通过上述两个方式实现单例模式,它们是线程安全的吗?
可以通过分析线程不安全产生的原因来判断;

饿汉模式:获取实例方法,只是读操作,不会修改变量,线程是安全的;
懒汉模式:多线程下,无法保证创建对象的唯一性, 线程是不安全的;

懒汉模式下两个线程调用getInstance:在这里插入图片描述

问题1 产生原因:
t1线程先执行 if 判断,准备创建实例但还没有创建,此时t2 进行 if 判断,进入代码块也准备拆改那就实例,这就造成创建多个实例的现象;=》相当于多个线程修改同一个变量了;
( if 和 new不是原子的,会造成创建多个实例对象;创建过多会非常占内存空间,导致线程不安全;)

解决问题1方式:
加锁 保证 if 和 new 的原子性;
【注】加锁不一定线程安全,必须保证锁加对位置;

代码实现:

 public static SingletonLazy getInstance() {//给当前类对象加锁synchronized (SingletonLazy.class) {if(instance == null) {instance = new SingletonLazy();}}return instance;}

问题2:
每次调用genInstance都会触发锁竞争,让加锁操作变得低效;

通过问题可以发现,懒汉模式的线程不安全,只出现在首次创建对象,一定对象创建完毕,后续调用getInstance,就只是读操作,就不会产生线程安全;=》只给第一次加锁即可;

解决问题2 方式:使用双重 if 解决
① 外层:判断是否要加锁
② 内层:判断是否创建对象

代码实现:

public static SingletonLazy getInstance() {//判断是否要加锁,如果有对象就不必加锁,此时是线程安全的//外层判断是否要加锁if(instance == null) {synchronized (SingletonLazy.class) {//等到调用的时候,才创建实例//里层判断是否创建对象if(instance == null) {instance = new SingletonLazy();}}}//如果有了实例直接返回,也保证了只要一个实例return instance;}

问题3:
多线程调用getInstance 进入操作会遇到new SingletonLazy操作, 创建实例会产生指令重排序问题;

创建实例一般有三步操作:
① 创建内存
② 调用构造方法 (初始化)
③ 把内存地址,赋给引用
原因:但是②③顺序不能够确定,假设两个线程t1,t2; t1可能先执行③顺序操作,此时t2执行 if判断,发现instance不为空,直接返回,而t1没有初始化变量等,t2只是拿到了不完整的实例对象,直接使用就会造成线程安全
【注】上述指令重排序发生的概率很小,但不能忽视;

解决问题3 :使用volatile 禁止指令重排序

    volatile private static SingletonLazy instance = null;

2.3.4 小结懒汉模式下产生的线程不安全

解决懒汉模式下的线程不安全方式:
① 加锁把 if 和 new操作变成原子的;
② 双重 if 减少不必要的加锁操作;
③ 使用 volatile 禁止指令重排序,保证后续线程能拿到完整对象;


总结

✨✨✨各位读友,本篇分享到内容如果对你有帮助给个👍赞鼓励一下吧!!
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!

http://www.dinnco.com/news/25161.html

相关文章:

  • 手机优化助手怎么关闭网站推广优化设计方案
  • 厦门b2b网站建设神马seo服务
  • 一个服务器可以做两个网站国际重大新闻事件2023
  • 手机网站怎么做今天发生的重大新闻内容
  • 做网站开公司东莞网站建设
  • 浙江网站备案加急合肥网站优化seo
  • 浙江省嘉兴建设局官方网站网推怎么做最有效
  • 公司网站建设的费用如何入账网页模板怎么用
  • 小程序怎么做优惠券网站东莞营销网站建设直播
  • asp网站 攻击怎么做个网站
  • 接帮人家做网站的网站株洲seo优化报价
  • 南京做网站优化的公司百度灰色关键词排名代做
  • 专业房产网站建设营销推广方案ppt案例
  • 新手如何建设网站app推广30元一单
  • 做策划有帮助的网站域名注册网站系统
  • 网站建设 落地页肇庆seo
  • 深圳网站网站开发软文自助发稿平台
  • 网站开发背景鼠标跟随重庆seo团队
  • 武汉专业做网站jw100十大经典事件营销案例
  • 厦门企业网站建设怎么建网站详细步骤
  • 网站的制作步骤聚名网官网
  • 可信网站验证多少钱seo网站推广多少钱
  • 电子商务网站建设收益举例谷歌浏览器下载app
  • 网站做微信接口吗优化是什么意思?
  • 网站模板化河南网站排名
  • 建筑工程 网络图电脑系统优化软件
  • 网站使用标题做路径永久免费低代码开发平台
  • openshift 做网站国内ip地址 免费
  • 广州火车站刺激广告
  • 专业做酒的网站有哪些网店怎么推广和宣传