当前位置: 首页 > 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.ritt.cn/news/10909.html

相关文章:

  • 做影视网站如何通过备案付费推广方式有哪些
  • 转转怎么做钓鱼网站刷百度关键词排名优化
  • 个人网站页面模板htmlseo优化排名怎么做
  • 佛山市南海区交通建设网站云建站模板
  • 三杰网站建设电商广告网络推广
  • 河北共产党员网站两学一做销售外包公司
  • app网站开发学习济南百度竞价代运营
  • 泉州建站模板搭建广告优化师是做什么的
  • 家装网站建设长尾关键词挖掘精灵
  • 本地企业网站建设模板网络优化app哪个好
  • 上海网站建设 迈免费收录网站提交
  • 个人网站免费建站常用seo站长工具
  • 深圳龙岗建网站公司站长工具中文
  • 成都学校网站建设企业百度seo营销推广多少钱
  • 丰台做网站公司百度关键词搜索排名
  • 象刀设计网站百度seo关键词排名优化工具
  • 企业宣传网站在哪里做seo网页优化培训
  • 推荐网站建设案例湖南发展最新消息公告
  • 大型企业网站建设东莞seo推广公司
  • wordpress 申请优化算法
  • 做美国市场哪个网站好什么是淘宝搜索关键词
  • 网站域名被劫持域名ip查询
  • 一个网站不兼容ie怎么做关键词推广优化app
  • 青岛博彩做网站多少钱学新媒体运营最好的培训学校
  • 设计师做私单网站做搜索引擎推广多少钱
  • 如何联系网站搜索网站排名
  • 甘肃省网站备案优化培训方式
  • 新津网站建设潍坊住房公积金
  • 重庆企业网站建设价格百度快照推广是什么意思
  • 高港区住房和城乡建设局网站如何在互联网上做推广