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

网站建设工作汇报免费ftp空间

网站建设工作汇报,免费ftp空间,seo评价网,网站没有备案做竞价吗什么是单例模式? 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创 建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象&#x…

什么是单例模式?

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创

建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有唯一的对象实例被创建。这个类提供 了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

应用场景

主要被用于一个全局类的对象在多个地方被使用并且对象的状态是全局变化的场景下。

单例模式的优点

单例模式为系统资源的优化提供了很好的思路,频繁创建和销毁对象都会增加系统的资源消耗,而单例模式保障了整个系统只有一个对象能被使用,很好地节约了资源。

单例模式的实现?

单例模式的实现常用的有两种方法,一种是懒汉式,另一种是饿汉式。

饿汉式:在类初始化的时候就生成对象实例。

懒汉式:在调用获取的方法时才生成对象实例。

与饿汉式对比,懒汉式一开始需要的内存较少,但是饿汉式由于初始化是在类初始化时就完成,所以是多线程安全的,懒汉式还需要解决线程安全问题。

饿汉式单例

public Singleton {//在类的初始化时就创建对象,这里可以解决多线程访问的安全问题。private static Singleton instance = new Singleton();// 另外一种初始化,就是采用静态代码块的方式。// static {//     instance = new Singleton();// }private Singleton(){}public static Singleton getInstance(){return instance;}
}

懒汉式单例

public class LazySingleTon {private static LazySingleTon instance;private LazySingleTon() {}// 这里需要对多线程访问的情况进行处理,保证多线程安全,使用synchronized进行加锁操作。public static synchronized LazySingleTon getInstance() {if (instance == null) {instance = new LazySingleTon();}return instance;}
}

以上使用synchronized关键字是解决多线程情况下的并发导致的多次创建对象的问题。由于synchronized关键字加的锁属于重量级锁,对于性能有一定的影响,一般不推荐使用这种方法,下面还有双重检查加锁的方式。

双重检查的懒汉式单例

public class DoubleCheckSingleTon {// 使用volatile关键字解决指令重排的问题。private volatile static DoubleCheckSingleTon instance;private DoubleCheckSingleTon() {}public static DoubleCheckSingleTon getInstance() {// 判断是否已经完成了实例初始化if (instance == null) {// 对创建对象的过程进行加锁,以防多线程访问出现多次初始化的问题。synchronized (DoubleCheckSingleTon.class) {if (instance == null) {instance = new DoubleCheckSingleTon();}}}return instance;}
}
详细解释一下指令重排的问题

由于没有加锁,当线程A刚执行完if判断instance为null后开始执行 instance = new DoubleCheckSingleTon();

注意,new DoubleCheckSingleTon()这个操作在JVM层面不是一个原子操作

具体由三步组成:

1.为instance分配内存空间;

2.初始化instance;

3.将instance指向分配的内存空间。

且这三步在JVM层面有可能发生指令重排,导致实际执行顺序可能为1-3-2,因为new操作不是原子化操作,因此,可能会出现线程A执行new DoubleCheckSingleTon()时发生指令重排的情况,导致实际执行顺序变为1-3-2,当执行完1-3还没来及执行2时(虽然还没执行2,但是对象的引用已经有了,只不过引用的是一个还没初始化的对象,此时线程B进来进行if判断后instance不为null,然后直接把线程A new到一半的对象返回了。使用volatile可以禁止指令重排,可以解决此问题。

其它单例模式的实现

内部静态类单例

public class StaticClassSingleton {private static class SingletonHolder {private static final StaticClassSingleton INSTANCE = new StaticClassSingleton();}private StaticClassSingleton() {}public static StaticClassSingleton getInstance() {return SingletonHolder.INSTANCE;}
}

内部静态类单例可以在调用类的静态方法时,再去完成对象的初始化,这样可以在类初始化时,节省一部分内存。

枚举单例

public enum Singleton {INSTANCE;
}

枚举由于是由JVM管理,所以线程安全等问题不需要处理。

破坏单例模式

破坏单例模式有两种方式,分别是序列化和反射。

序列化

public HungrySingleTon implements Serializable{//在类的初始化时就创建对象,这里可以解决多线程访问的安全问题。private static HungrySingleTon instance = new Singleton();private HungrySingleTon(){}public static HungrySingleTon getInstance(){return instance;}
}

将单例对象实例序列化到磁盘上,再反序列化回来。

public class TestSingleton {public static void main(String[] args) throws Exception {TestSingleton testSingleton = new TestSingleton();testSingleton.writeToDisk();testSingleton.reloadFromDisk();testSingleton.reloadFromDisk();}public void writeToDisk() throws Exception {HungrySingleTon instance = HungrySingleTon.getInstance();ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\singleton.obj"));objectOutputStream.writeObject(instance);objectOutputStream.close();}public void reloadFromDisk() throws Exception{ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\singleton.obj"));HungrySingleTon singleTon = (HungrySingleTon) objectInputStream.readObject();System.out.println(singleTon);}
}//****************调用结果如下**************
// com.code.designpattern.HungrySingleTon@182decdb
// com.code.designpattern.HungrySingleTon@26f0a63f
// Process finished with exit code 0

以上调用结果显示,经过序列化和反序列化后,单例模式的结果被破坏了。

解决办法

在单例类中添加一个加 readResolve() 方法,在反序列化时被反射调用,如果定义了这个方法,

就返回这个方法的值,如果没有定义,则返回新new出来的对象。

public HungrySingleTon implements Serializable{//在类的初始化时就创建对象,这里可以解决多线程访问的安全问题。private static HungrySingleTon instance = new Singleton();private HungrySingleTon(){}public static HungrySingleTon getInstance(){return instance;}// 添加readResolve方法解决破坏单例的问题。public Object readResolve() {return instance;}
}
readResolve方法原理

ObjectInputStream类中的readObject方法

public final Object readObject() throws IOException,
ClassNotFoundException{
...
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
try {Object obj = readObject0(false);//重点查看readObject0方法
.....
}
private Object readObject0(boolean unshared) throws IOException {
...
try {switch (tc) {
...case TC_OBJECT:return checkResolve(readOrdinaryObject(unshared));//重点//查看readOrdinaryObject方法
...}} finally {depth--;bin.setBlockDataMode(oldMode);}
}private Object readOrdinaryObject(boolean unshared) throws IOException
{
...
//isInstantiable 返回true,执行 desc.newInstance(),通过反射创建新的单例
//类,obj = desc.isInstantiable() ? desc.newInstance() : null;
...
// 在Singleton类中添加 readResolve 方法后 desc.hasReadResolveMethod()
//方法执行结果为trueif (obj != null && handles.lookupException(passHandle) == null &&desc.hasReadResolveMethod()) {
// 通过反射调用 Singleton 类中的 readResolve 方法,将返回值赋值给rep变
//量
// 这样多次调用ObjectInputStream类中的readObject方法,继而就会调用我们
// 定义的readResolve方法,所以返回的是同一个对象。Object rep = desc.invokeReadResolve(obj);
...}return obj;
}

反射

反射调用单例,破坏单例模式。

public class TestSingletonQuestion {public static void main(String[] args) throws Exception {Constructor<HungrySingleTon> declaredConstructor = HungrySingleTon.class.getDeclaredConstructor();declaredConstructor.setAccessible(true);HungrySingleTon instance = declaredConstructor.newInstance();HungrySingleTon instance1 = declaredConstructor.newInstance();System.out.println(instance1 == instance);}
}
解决反射破坏单例模式的办法

可以通过在私有的构造函数中判断当前对象是否已经初始化过,也可以添加一个静态的标志变量,用以表示是否已经初始化过对象实例,如果初始化过,就直接抛出异常,达到单例构造器禁止反射多次调用的方式。

下面写出标志变量的方法

package com.code.designpattern;import java.io.Serializable;public class HungrySingleTon implements Serializable {private static HungrySingleTon instance = new HungrySingleTon();// 静态标志变量,用于标识是否初始化过实例对象。private static boolean flag = false;private HungrySingleTon() {if (flag) {throw new RuntimeException("单例构造器禁止反射调用");}flag = true;}public static HungrySingleTon getInstance() {return instance;}public static void main(String[] args) {HungrySingleTon instance1 = HungrySingleTon.getInstance();HungrySingleTon instance2 = HungrySingleTon.getInstance();System.out.println(instance1 == instance2);}public Object readResolve() {return instance;}}
http://www.dtcms.com/wzjs/552818.html

相关文章:

  • 网站空间 支持什么程序51ape是谁做的网站
  • 多少钱做网站什么叫网页
  • 网站建设大公司怎么建设游戏平台网站
  • 厚街响应式网站建设网络小说网站三巨头
  • 怎么建立自己的网站平台衣服网站建设方案书
  • 邯郸市做网站的公司电商推广方案
  • 泸州建设工程质量监督网站国外电商怎么做
  • 大连网站建设蛇皮果公司一个人做网站
  • 电子商务网站开发与应用网站开发命名规范
  • 个人网站做淘客dede做英文网站优化
  • 个人网站开发公司一个人看的免费直播大全
  • 网站管理助手4.0 破解温岭市建设规划局网站
  • 室内设计网站有哪些比较好亚马逊关键词优化软件
  • vs2015 asp网站开发石家庄关键词排名工具
  • 如何建立网站卖东西免费服务器有哪些
  • 网站建设综合案例响应式网站建设
  • python3网站开发做网站的简称
  • 全国当先的网络建站推广互粉的网站是怎么做的
  • 网站建设倒计时代码做网站推广业务怎么样
  • 专业东莞网站制作公司北京制作网页设计
  • 融资渠道长春seo优化企业网络跃升
  • 做网站购买服务器吗wordpress 小说 采集器
  • 家具网站开发设计任务书seo知识总结
  • 手机网站建设公司排名郑州网站建设定制开发
  • 宣讲家网站做四讲四有模范网站开发的行业情况分析
  • 自己建的网站如何百度搜索菜鸟教程网官网入口
  • dede网站如何换源码如何写好软文
  • 推广网站怎么做西昌seo
  • 合肥企业制作网站深圳市建筑工程股份有限公司
  • 个人性质网站名称精品课程网站建设设计方案