Java单例模式

it2022-05-05  185

Java单例模式

1、饿汉模式:直接创建对象,不存在线程安全问题

1.1、直接实例化(简洁直观)
/** * @author luojianhui * @date 2018/11/2 * 直接实例化 * 1.构造器私有化 * 2.自行创建,并用静态变量保存 * 3.向外提供这个实例 * 4.强调这是一个单例,用final修改 * 5.随着类加载初始化,静态修饰对象也会创建 */ public class Singleton1 { public static final Singleton1 INGLETON=new Singleton1(); private Singleton1() { } }
1.2、枚举式(最简洁)(jdk 1.5之后)
/** * @author luojianhui * @date 2018/11/2 * 枚举式 * 1.枚举类型:表示该类型的对象是有限的几个 * 2.限定为一个,就成为单例了 */ public enum Singleton2 { INSTANCE }
1.3、静态代码块(适合复杂实例化)
/** * @author luojianhui * @date 2018/11/2 * 静态代码块 * 1.随着类加载初始化,静态代码块也执行 */ public class Singleton3 { public static final Singleton3 SINGLETON; private String info; static { try { //初始化Properties Properties pro = new Properties(); //文件最终编译是在类路径下 pro.load(Singleton3.class.getClassLoader().getResourceAsStream("singleton.properties")); INGLETON = new Singleton3(pro.getProperty("info")); } catch (IOException e) { throw new RuntimeException(); } } private Singleton3(String info) { this.info = info; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Override public String toString() { return "Singleton3{" + "info='" + info + '\'' + '}'; } }

singleton.properties 放在src目录下

info=ash

测试:

public class TestDemo{ public static void main(String[] args) { Singleton3 ingleton = Singleton3.INGLETON; System.out.println(ingleton.toString()); //输出结果:Singleton3{info='ash'} } }

这种方式就像一些框架加载配置文件

2、懒汉模式:延迟创建对象

2.1、线程不安全(适用于单线程)
/** * @author luojianhui * @date 2018/11/2 */ public class Singleton4 { //静态变量保存唯一实例 private static Singleton4 singleton; private Singleton4() { } public static Singleton4 getInstance() { if (singleton == null) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } singleton = new Singleton4(); } return singleton; } }

测试:

/** * @author luojianhui * @date 2018/9/12 */ public class TestDemo { public static void main(String[] args) throws ExecutionException, InterruptedException { //创建线程 Callable<Singleton4> callable = new Callable<Singleton4>() { @Override public Singleton4 call() throws Exception { return Singleton4.getInstance(); } }; //创建两个线程池 ExecutorService es = Executors.newFixedThreadPool(2); Future<Singleton4> f1 = es.submit(callable); Future<Singleton4> f2 = es.submit(callable); Singleton4 singleton4 = f1.get(); Singleton4 singleton41 = f2.get(); System.out.println(singleton4 == singleton41); //输出结果:false es.shutdown(); } }

原因:当一个线程进入休眠,另一个线程此时判断singleton为null,两个线程都执行了if语句,所有创建了两个不能的实例

2.2、线程安全(适用于多线程)
/** * @author luojianhui * @date 2018/11/2 */ public class Singleton5 { //静态变量保存唯一实例 private static Singleton5 singleton; private Singleton5() { } public static Singleton5 getInstance() { //使用类作为锁对象 synchronized (Singleton5.class) { if (singleton == null) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } singleton = new Singleton5(); } return singleton; } } } 锁
2.3、静态内部类形式(适用于多线程)
/** * @author luojianhui * @date 2018/11/2 * 在内部类被加载和初始化时,才创建实例对象 * 静态内部类不会自动随着外部类的加载和初始化而初始化,他是要单独去加载和初始化的 * 因为是在内部类加载和初始化时创建的,因此是线程安全的 */ public class Singleton6 { private Singleton6() { } private static class Inner { private static final Singleton6 SINGLETON_6 = new Singleton6(); } public static Singleton6 getInstance() { return Inner.SINGLETON_6; } }

转载于:https://www.cnblogs.com/laoash/p/9897497.html


最新回复(0)