java单例模式(饿汉式和懒汉式的几种不同写法)
程序员文章站
2022-04-05 09:55:13
...
1.饿汉式(直接创建)三种创建方法代码里面都有
第三种静态代码块方式,需要创建个properties文件
package java2;
import java.io.IOException;
import java.util.Properties;
/**
* 单例模式设计步骤:
* 1.构造器私有化
* 2.内部创建对象实例,并用静态变量保存
* 3.向外提供获取的方法
* 强调这是一个单例,我们可以用final修改
*
*/
/**
* 一、饿汉式:在类初始化时直接创建对象,不管你是否需要这个对象,不存在线程安全问题
*
* (1.1)直接创建实例对象
*/
class Singleton1{
public static final Singleton1 INSTANCE = new Singleton1();
private Singleton1(){}
}
/**
* (1.2)枚举类型,就是该类型对象是有限个
*/
enum Singleton2 {
INSTANCE
}
/**
* (1.3)静态代码块方法
*/
class Singleton3{
public static final Singleton3 INSTANCE;
private String info;
//如何构造器传的值需要从文件里获取,那么就需要用到静态代码来实现单例
static {
try {
Properties pro = new Properties();
pro.load(Singleton3.class.getClassLoader().getResourceAsStream("Single.properties"));
INSTANCE = new Singleton3(pro.getProperty("info"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private Singleton3(String info){
this.info = info;
}
}
public class Singleton_e {
public static void main(String []args){
Singleton1 singleton1 = Singleton1.INSTANCE;
System.out.println(singleton1);
//枚举类型这里直接打印出来了,因为枚举重写了toString方法
Singleton2 singleton2 = Singleton2.INSTANCE;
System.out.println(singleton2);
Singleton3 singleton3 = Singleton3.INSTANCE;
System.out.println(singleton3);
}
}
懒汉式(用到的时候才创建)三种创建方法
package java2;
/**
* 二、懒汉式:演示创建这个实例对象
*
* (1)构造器私有化
* (2)用一个静态变量保存这个唯一实例
* (3)提供一个静态方法,获取这个实例对象
*/
import java.util.concurrent.*;
/**
* (2.1)多线程下,线程不安全
*/
class Singleton4{
private volatile static Singleton4 INSTANCE = null;
private Singleton4(){
System.out.println(Thread.currentThread().getName()+"\t线程调用构造");
}
public static Singleton4 getINSTANCE() {
if (INSTANCE == null){
INSTANCE = new Singleton4();
}
return INSTANCE;
}
}
/**
* (2.2)改进版volatile+双端检索机制
*/
class Singleton5{
private volatile static Singleton5 INSTANCE = null;
private Singleton5(){
System.out.println(Thread.currentThread().getName()+"\t线程调用构造");
}
//这里用volatile+双端检索机制
public static Singleton5 getINSTANCE() {
try {TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
if (INSTANCE == null) {
synchronized (Singleton5.class)
{
if (INSTANCE == null){
INSTANCE = new Singleton5();
}
}
}
return INSTANCE;
}
}
/**
*(2.3)静态内部类形式,线程安全的
* 在内部类被加载和初始化时,才会创建INSTANCE实例对象
* 静态内部类不会自动随外部类的加载和初始化而初始化,它是要单独去加载和初始化的
* 因为是在内部类加载和初始化时,创建的,因此是线程安全的
*/
class Singleton6{
private Singleton6() { }
//静态内部类(就是类的内部加了个静态的饿汉式?我是这样理解的)
private static class Inner{
private static final Singleton6 INSTANCE = new Singleton6();
}
//获取
public static Singleton6 getInstance(){
return Inner.INSTANCE;
}
}
public class Singleton_lan {
public static void main(String []args) throws ExecutionException, InterruptedException {
//(2.1)多线程下,线程不安全
Singleton4 singleton4 = Singleton4.getINSTANCE();
//(2.2)改进版
Callable<Singleton5> callable = new Callable<Singleton5>() {
@Override
public Singleton5 call() throws Exception {
return Singleton5.getINSTANCE();
}
};
ExecutorService threadpool = Executors.newFixedThreadPool(2);
Future<Singleton5> f1 = threadpool.submit(callable);
Future<Singleton5> f2 = threadpool.submit(callable);
Singleton5 s1 = f1.get();
Singleton5 s2 = f2.get();
threadpool.shutdown();
System.out.println(s1 == s2);
System.out.println(s1);
System.out.println(s2);
//(2.3)静态内部类形式
Singleton6 singleton6 = Singleton6.getInstance();
System.out.println(singleton6);
}
}
上一篇: 1.计算字符串最后一个单词的长度
下一篇: 第4章:Java基本概念