JAVA面试-单例

 1.单例的常见形式

 2.饿汉式

类一被加载就创建对象,不管是否需要。创建的很着急,所以称为饿汉式。

2.1直接实例化

package singleton;

/*饿汉式:直接创建实例对象,不管你需不需要都会创建(因为static关键字)
 *特点如下:
 * 1.构造器私有化
 * 2.自行创建,并且用静态变量保存
 * 3.向外提供这个实例
 * 4.可以通过final关键字强调这是一个单例
 *
 * 缺点:
 * 1.实例对象不管你需不需要都会创建,浪费资源
 *
 */
public class Singleton01 {
    public static  final Singleton01 SINGLETON_01 =new Singleton01();
    private Singleton01() {

    }
    public void say(){
        System.out.println("Singleton01.say()");
    }


}

2.2 枚举(其实简单)

package singleton;

/*
 *枚举类型:表示该类型的对象是有限的几个
 * 我们可以限定为一个,就成了单例
 */
public enum Singleton02 {
    INSTANCE;

    public void say(){
        System.out.println("enum");
    }
}

2.3 静态代码块

2.3.1 简单版

package singleton;

/**
 *若构造方法有参 则使用静态代码块较好
 * 否则 还是使用简单单例
 */
public class Singleton03 {
    public static  final  Singleton03 SINGLETON_03;

    private String info;
    static {
       SINGLETON_03=new Singleton03("name") ;
//       报错:this和super关键字不能在static修饰的内容中使用
//       SINGLETON_03=new Singleton03(this.info) ;
    }
    private Singleton03(String info){
        this.info=info;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

}

2.3.2 升级版(从配置文件读入)

package singleton;

import java.io.IOException;
import java.util.Properties;

/**
 * 使用配置文件读入参数
 */
public class Singleton03Plus {
    public static final Singleton03Plus SINGLETON_03_PLUS;
    private String name;
    private String age;

    static {

        try {
//            配置文件放在Resource文件夹下
            Properties properties = new Properties();
            properties.load(Singleton03Plus.class.getClassLoader().getResourceAsStream("single.properties"));
            SINGLETON_03_PLUS = new Singleton03Plus(properties.getProperty("name"), properties.getProperty("age"));
            System.out.println(properties);
        } catch (IOException e) {
//            一定要抛出这个异常
            throw new RuntimeException(e);
        }

    }

    private Singleton03Plus(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Singleton03Plus{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

2.3.3 配置文件single.properties内容

info=xiongdu
name=zhangsan
age=12

3 懒汉式

懒汉式:延迟创建该实例对象(在需要的时候创建(第一次需要时创建))

3.1 线程不安全

package singleton.singleton2;

/**
 * 懒汉式:延迟创建该实例对象(在需要的时候创建(第一次需要时创建))
 *特点:
 * 1.构造器私有化
 * 2.用一个静态变量保存这个唯一的实例
 * 3.提供一个静态方法,创建或获取这个实例
 *
 */
public class Singleton1 {
    private static Singleton1 singleton1;
    private Singleton1(){

    }
    public static Singleton1 getInstance(){
        if(singleton1==null) {
            singleton1 = new Singleton1();
        }

        return singleton1;
    }
}

3.2 线程安全

package singleton.singleton2;

/*
 *加锁实现线程安全
 */
public class Singleton2 {
    private static Singleton2 singleton2;
    private Singleton2(){

    }
    public static Singleton2 getInstance(){
        if(singleton2==null){
            synchronized (Singleton2.class){
                //双重验证 保证线程安全
                if(singleton2==null){
                    singleton2=new Singleton2();
                }
                }
            }
        return singleton2;
    }
}

3.3 静态内部类(推荐使用)

package singleton.singleton2;

/**
 * 推荐使用:
 *
 * 1.在内部类被加载和初始化时,才创建实例对象
 * 2.静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的
 * 3.因为是在内部类加载和初始化的,创建的,因此是线城安全的
 */
public class Singleton3 {
    private Singleton3(){

    }
    private static class Inner{
        private static final Singleton3 SINGLETON_3=new Singleton3();
    }
    public static Singleton3 getInstance(){
        return Inner.SINGLETON_3;
    }
}

3.4 多线程测试

package singleton.singleton2;

import java.util.concurrent.*;

public class TestSingleton2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        Callable<Singleton2> c = new Callable<Singleton2>() {

            @Override
            public Singleton2 call() throws Exception {
                return Singleton2.getInstance();
            }
        };

        ExecutorService es = Executors.newFixedThreadPool(2);
        Future<Singleton2> f1 = es.submit(c);
        Future<Singleton2> f2 = es.submit(c);

        Singleton2 s1 = f1.get();
        Singleton2 s2 = f2.get();

        System.out.println("s1==s2 = " + (s1 == s2));
        System.out.println("s1 = " + s1);
        System.out.println("s2 = " + s2);

        es.shutdown();

    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值