我是靠谱客的博主 淡淡麦片,最近开发中收集的这篇文章主要介绍java 懒加载模式_java设计模式-单例模式及其几种实现方式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.定义

确保一个类只有一个实例,并提供一个全局访问点。

2.实现方式

2.1 声明即创建对象方式

package com.methon.singleton;

public class SigDemo01 {

private static SigDemo01 INSTANCE=new SigDemo01 ();

private SigDemo01 (){};

public static SigDemo01 getInstance(){

return INSTANCE;

}

public static void main(String[] args) {

SigDemo01 sig01=SigDemo01 .getInstance();

SigDemo01 sig02=SigDemo01 .getInstance();

/* 判断是否是同一个对象 */

System.out.println(sig01==sig02);

}

}

其中static声明的静态成员INSTANCE只会在类加载的时候创建一次,new一个对象。

私有的构造函数保证只能在此类中调用,其他类中想要获取实例只能调用getInstance()方法。

返回static对象。保证对象的唯一性。上面的代码也可以写成:

package com.methon.singleton;

public class SigDemo02{

private static SigDemo02 INSTANCE;

static {

INSTANCE=new SigDemo02();

}

private SigDemo02(){};

public static SigDemo02 getInstance(){

return INSTANCE;

}

public static void main(String[] args) {

SigDemo02 sig01=SigDemo02.getInstance();

SigDemo02 sig02=SigDemo02.getInstance();

/* 判断是否是同一个对象 */

System.out.println(sig01==sig02);

}

}

2.2 懒加载方式

以下为懒加载方式的演变,方法逐渐变得趋于完美

2.2.1 错误的懒加载写法(不支持多线程)

package com.methon.singleton;

public class SigDemo03{

private static SigDemo03 INSTANCE;

private SigDemo03(){

}

public static SigDemo03 getInstance(){

if(INSTANCE==null){

INSTANCE=new SigDemo03();

}

return INSTANCE;

}

public static void main(String[] args) {

for (int i = 0; i < 100; i++) {

new Thread(()-> System.out.println(SigDemo03.getInstance().hashCode())).start();

}

}

}

如果代码中没有多线程,则程序没有任何问题。但存在多线程的情况下,执行到if(INSTANCE==null)后, INSTANCE=new SigDemo03()语句前,可能有多个线程通过了if(INSTANCE==null)的判断,从而不能保证创建出的对象有且仅有1个。

2.2.2 懒加载的正确写法(加锁)

package com.methon.singleton;

public class SigDemo04{

private static SigDemo04 INSTANCE;

private SigDemo04() {

}

public static synchronized SigDemo04 getInstance() {

if (INSTANCE == null) {

INSTANCE = new SigDemo04();

}

return INSTANCE;

}

public static void main(String[] args) {

for (int i = 0; i < 100; i++) {

new Thread(() -> System.out.println(SigDemo04.getInstance().hashCode())).start();

}

}

}

对比之前的方法,只是在getInstance()方法上添加了synchronized ,保证了线程安全。但这样做的话降低了程序的执行效率。

2.2.3 为了解决加锁后程序效率变低而采取的错误处理

package com.methon.singleton;

public class SigDemo05{

private static SigDemo05 INSTANCE;

private SigDemo05() {

}

public static SigDemo05 getInstance() {

if (INSTANCE == null) {

synchronized (SigDemo05.class) {

INSTANCE = new SigDemo05 ();

}

}

return INSTANCE;

}

public static void main(String[] args) {

for (int i = 0; i < 100; i++) {

new Thread(() -> System.out.println(SigDemo05 .getInstance().hashCode())).start();

}

}

}

为了提高效率,在判断INSTANCE == null之后在进行加锁的判断。但是请注意,虽然进行了加锁操作,但是最后线程们都会创建新的对象。

2.2.4 为了解决加锁后程序效率变低而采取的正确处理

package com.methon.singleton;

public class SigDemo06{

private static SigDemo06 INSTANCE;

private SigDemo06 () {

}

public static SigDemo06 getInstance() {

if (INSTANCE == null) {

synchronized (SigDemo06 .class) {

if (INSTANCE == null) {

INSTANCE = new SigDemo06 ();

}

}

}

return INSTANCE;

}

public static void main(String[] args) {

for (int i = 0; i < 100; i++) {

new Thread(() -> System.out.println(SigDemo06 .getInstance().hashCode())).start();

}

}

}

此方式虽然有些繁琐,但是正确的做法。在判断INSTANCE == null后进行加锁,之后在进行判空操作。仍为空后在进行new新的对象。避免了只要为空就会创建新的对象。

2.2.5 较完美的静态内部类方式

package com.methon.singleton;

public class SigDemo07{

private SigDemo07() {

}

public static SigDemo07 getInstance() {

return SigDemo07Holder.INSTANCE;

}

private static class SigDemo07Holder {

private final static SigDemo07 INSTANCE = new SigDemo07();

}

public static void main(String[] args) {

for (int i = 0; i < 100; i++) {

new Thread(() -> System.out.println(SigDemo07.getInstance().hashCode())).start();

}

}

}

此种方式,避免了声明即创建对象的方式,采用静态内部类的方式,需要时才创建对象。比较完美且代码不冗余。

2.2.6 effictive java给出的方式

package com.methon.singleton;

public enum SigDemo08{

INSTANCE;

public static void main(String[] args) {

for (int i = 0; i < 100; i++) {

new Thread(() -> System.out.println(SigDemo08.INSTANCE.hashCode())).start();

}

}

}

直接设置成了枚举类型,且仅有一个枚举量INSTANCE。

3.总结

正常需要单例模式的情况一般都需要创建对象。所以是否进行懒加载区别相差不大。故方法2.1满足平常使用的要求。除此之外,方法2.2.4, 2.2.5, 2.2.6更为完美,推荐使用。

最后

以上就是淡淡麦片为你收集整理的java 懒加载模式_java设计模式-单例模式及其几种实现方式的全部内容,希望文章能够帮你解决java 懒加载模式_java设计模式-单例模式及其几种实现方式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部