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

网站建设投标文档300个好听的公司名字大全

网站建设投标文档,300个好听的公司名字大全,wordpress怎么调用分类的文章,lamp wordpress主题目录 一. 设计模式 二. 单例模式 2.1 饿汉模式 2.2 懒汉模式 a. 加锁synchronized b. 双重if判定 c. volatile关键字(双重检查锁定) 一. 设计模式 设计模式是在软件工程中解决常见问题的经典解决方案。针对一些特定场景给出的一些比较好的解决…

目录

一. 设计模式 

二. 单例模式 

2.1 饿汉模式

2.2 懒汉模式

a. 加锁synchronized

b. 双重if判定

c. volatile关键字(双重检查锁定)


一. 设计模式 

   设计模式是在软件工程中解决常见问题的经典解决方案。针对一些特定场景给出的一些比较好的解决方案,只要按照设计模式来写代码,就可以使代码不会太差(保证了代码的下限)。

   设计模式比较适用于C++,Java,C#,但是对于 Python 或 Erlang 这些语言,这里的很多设计模式都是不适用的。设计模式适合具有一定的编程经验之后再去学习,如果缺少编程经验,会比较难以理解。

二. 单例模式 

   单例模式 是Java中最简单的设计模式之一,它确保一个类只有一个实例,并提供一个全局访问点。一个Java程序中,某个类要求只有唯一一个实例,适合使用单例模式(单例模式前提是“一个进程中”,如果有多个Java进程,自然每个进程中都可以有一个实例了)

在Java中,实现单例模式主要有两种方式:“饿汉模式”“懒汉模式”

单例模式三部曲

  • static 修饰 instance 成员变量(类变量)
  • 构造方法私有
  • 静态全局访问点
2.1 饿汉模式

    在饿汉模式中,单例对象在类加载时就被立即初始化。这意味着类加载完成后,单例对象就已经创建好了,不管你是否需要它。

public class SingletonEager {//静态实例变量private static SingletonEager instance = new SingletonEager();//构造方法私有private SingletonEager(){}//全局访问点(每次需要通过getInstance来获取实例的)public static SingletonEager getInstance(){return instance;}
}

饿汉模式中的 “饿” 的意思是 “迫切”(eager),即在类被加载的时候,就会创建出这个单例的实例。

优点

  • 简单易实现,类加载时就完成了实例化,避免了线程安全问题

缺点

  • 如果自始至终未使用过这个实例,则会造成内存浪费
2.2 懒汉模式

    在懒汉模式中,单例对象在第一次使用时才进行初始化。这种方式可以延迟对象的创建,只有在实际需要时才会创建对象。

public class SingletonLazy {//静态变量声明时不初始化private static SingletonLazy instance;//构造方法私有private SingletonLazy(){}//初次使用会进行初始化public static SingletonLazy getInstance(){if(instance == null){instance = new SingletonLazy();}return instance;}
}

懒汉模式中的 “懒” 的意思是推迟了创建实例的时机,首次调用getInstance,才会创建实例
计算机中,谈到的"懒"是褒义词,意思是效率会更高,能不搞就不搞,很多时候,就可以把这部分开销就省下了

相比饿汉模式,懒汉模式的效率会更高一些。

比如:有一个编辑器,打开一个非常大(1G)的文本文档

  • 一启动,就把所有的文本内容都读取到内存中,然后再显示到界面上 [饿汉]
  • 启动之后,只加载一小部分数据(一个屏幕能显示的最大数据),随着用户进行翻页操作,再按需加载剩下的内容  [懒汉]

很明显,懒汉模式会造成巨大的开销,而懒汉模式开销更小~~


* 但是,如果在多线程下,调用getInstance 是否会有线程安全问题呢?——  多个线程针对一个变量进行修改:如果只是读取,则没有问题;先判定,再修改的这种代码模式,属于典型的线程不安全代码,判定和修改之间可能涉及到线程的切换。

   当线程A初次调用 getInstance,判断 instance 为null,会执行创建实例(但还未执行就被调度走了的情况下);此时调度线程B,线程B刚好执行 getInstance,此时判断 instance 仍然为 null,又会执行一次创建实例。

   这样,同一个进程中就会执行两次创建实例的操作。虽然第二次创建,覆盖了 instance 的值,使得第一次创建的实例,没有引用指向,很快就会被垃圾回收机制给消除掉(instance 的引用仍是唯一的),但这样多次new操作已经造成了线程安全问题~~

   因此,需要对判断和初始化这两个操作打包成原子的.....


a. 加锁synchronized
public class SingletonLazy {private static SingletonLazy instance;private SingletonLazy(){}public static SingletonLazy getInstance(){//将判断和初始化操作打包成原子操作,加锁synchronized (SingletonLazy.class){if(instance == null){instance = new SingletonLazy();}}return instance;}
}

   注意此处的 return 操作不用加到同步代码块中。因为,无论 return 操作是在本线程还是其他线程,return的值都是Instance内存中最新的值!!


   加锁之后,确实解决了线程安全问题,但是加锁同样也可能带来阻塞.....

如果上述代码已经 new 完对象了,if 的判断分支再也进不去了,后续的代码 都是单纯的 读操作,已经没有线程安全问题了。但是以后只要调用 getInstance ,都会触发加锁操作,但在第一次初始化后,其实已经没有必要加锁了。加锁以后,还会产生阻塞,影响到性能。

   因此,针对这个问题,还要进一步改进——通过条件判断,在应该加锁的时候,才加锁;不需要加锁的时候,直接跳过加锁


b. 双重if判定
public class SingletonLazy {private static SingletonLazy instance;private SingletonLazy(){}public static SingletonLazy getInstance(){//再加一个if判断,instance不为null,直接返回值即可,不用加锁阻塞if(instance == null){synchronized (SingletonLazy.class){if(instance == null){instance = new SingletonLazy();}}}return instance;}
}

以往写的代码中,从未遇到过同样的if 连着写:

曾经的单线程代码中,这样的写法是毫无意义的,两个条件值一定相同。

但是在多线程代码中,任意两个代码之间,都可能穿插其他线程的逻辑。synchronized会使代码出现阻塞,一旦阻塞之后,啥时候恢复执行,是无法预知的。在这个过程中,很可能其他线程就把这个值给修改了~~

这俩条件,只是恰好写法一样,实际上,作用是完全不同的~~

外面的 if 判定 是否要加锁;里面的 if 是判定 是否要创建对象

只不过巧了!在这个代码中,通过同样的方式,完成上述两种判定的~~


但是,这个代码可能还会因为指令重排序(编译器优化),引起线程安全问题如果是单线程代码,编译器都能准确的进行判断;如果是多线程代码,编译器也是可能出现误判

 在创建实例 instance = new SingletonLazy () 时,这行代码实际上可以分解为以下三个操作:

     1. 分配内存空间

     2. 初始化对象

     3. 将对象引用指向分配的内存空间(执行后instance值不再为null)

在没有volatile关键字的情况下,编译器和处理器可能会对上述操作进行重排~~

例如:

     a. 分配内存空间

     b. 将对象引用指向分配的内存空间(执行后instance值不再为null)

     c. 初始化对象

如果发生了这种重排,假设 线程A 正在执行 instance = new SingletonLazy (),而 线程B 几乎同时调用 getInstance 方法,可能会发生以下情况:

  • 线程A 执行了 a 和 b,此时 instance 已经不为 null,但是对象还没有被初始化
  • 线程B 进入 getInstance 方法,执行第1次检查,发现 instance 不为 null,因此直接返回 instance
  • 线程B 在使用未完全初始化的 instance 时,可能会遇到空指针异常或其他错误。

    在Java中,所有的对象引用默认值都是null,如果声明了一个对象引用但没有进行初始化,那么试图访问这个引用的任何方法或属性都会抛出空指针异常

   此处相当于引用已经不为null了,但是没有为 instance 中的属性和方法进行初始化,因此使用 instance 的时候会抛出空指针异常。

   因此,为了解决这个问题,要对 instance 变量用 volatile关键字 修饰

* “指令重排序”的详细讲解在 JavaEE初阶(6)

* volatile 关键字的特性(保证“可见性”与“有序性”,不保证“原子性”)详细讲解在JavaEE初阶(8)

c. volatile关键字(双重检查锁定)
public class SingletonLazy {//volatile关键字修饰instanceprivate static volatile SingletonLazy instance;private SingletonLazy(){}public static SingletonLazy getInstance(){if(instance == null){synchronized (SingletonLazy.class){if(instance == null){instance = new SingletonLazy();}}}return instance;}
}

  volatile关键字 的作用之一就是禁止对 volatile变量 前后的操作进行指令重排。这样,当线程A创建 SingletonLazy 实例时,即使发生了指令重排,其他线程在读取 instance 变量时也能保证看到的是完全初始化后的对象。volatile 不仅保证了变量的可见性,还防止了指令重排可能带来的问题。

   换个角度看,加上volatile之后,也能禁止对 instance 赋值操作 插入到其他操作之间。


总结: 

设计模式:软件开发中,针对一些特定套路,给出的特定解决方案

单例模式

  • 饿汉模式:程序启动,类加载的时候,就会创建实例——不涉及线程安全问题
  • 懒汉模式:在程序第一次使用这个实例的时候,才会创建实例——涉及到线程安全问题

             a. 加锁把if判定和new赋值操作,打包成原子操作

             b. 双重 if 判定,解决加锁的性能问题

             c. volatile关键字解决指令重排问题

http://www.hyszgw.com/news/54720.html

相关文章:

  • 汕头公司做网站山西营销型企业网站开发
  • 什么招聘网最好找工作怎么优化网站关键词排名
  • 基金公司网站建设网站导航条设计欣赏
  • 网站建设增城wordpress joomla
  • 网站开发研发工程师岗位职责做网站需要什么手续
  • c 可以做网站吗1网站建设的目标是什么意思
  • 曲靖企业网站建设公司做的网站如何开启伪静态
  • 苏州cms模板建站宝书店网站的建设
  • 长沙网页建站把图片生成二维码的软件
  • 培训班招生方案有哪些嘉兴网站搜索优化
  • 凡科建站是永久的吗域名个人备案查询
  • 婚纱摄影网站河北沧州建设官方网站
  • 虾米音乐歌曲链接做qq音乐网站静态网站需要数据库吗
  • 百度推广需要备案的网站吗洛阳伟创科技
  • 怎么用ip做网站微视频网站源码
  • 商务网站设计素材wordpress 模板 怎么用
  • 滨州 网站开发华夏建筑工程网
  • ps做网站首页效果特效规划设计公司业务管理流程
  • 能看网站的浏览器东莞网站建设 包装材料
  • 网站制作怎样做背景公众号开发微商城
  • 蚌埠市建设管理局官方网站中国建设职业注册中心网站
  • 室内设计公司logoseo快速排名源码
  • 网站布局设计工具定制网站建设托管
  • 物流网站的建设方案总结好看的网站页面设计
  • 手机h5免费模板网站模板下载中信建设有限责任公司龙芳
  • 培训中心网站建设方案网站怎么做详情页
  • 岳阳做网站推荐崇明集团网站建设
  • 免费怎么制作公司网站搜索引擎优化技术有哪些
  • 大连开发区网站设计公司模板做的网站如何下载
  • 都网站建设邢台信息港房产