单例模式
1.1什么是单例
在程序运行中,只允许一个实例,不允许创建多个实例,这就称为单例。
1.2 单例设计模式的作用
在实际开发中,在系统或平台中中允许一个实例对象,这时就需用到单例模式。(例如,一个朝代只允许一个皇帝)
1.3单例模式原理
通过私有化构造方法,向外提供一个公开的方法获取实例
分析:
- 某个类只能有一个对象,但是构造方法只要一调用就会产生新的对象,可以通过封装将构造方法进行私有化;
- 若构造方法私有化,那么此类在外部不能创建对象,需要再类内部创建对象;
- 添加一个公开的方法,返回这个对象。
1.4实现方式
实现方式:
单例分为懒汉式和饿汉式
核心:
构造方法私有:不能在类外随意创建对象
在类内部声明一个本类静态的对象作为属性
提供一个共有静态的方法用来获取本类对象
饿汉式实现代码
public class Boss{
//属性
private String name;
private int age;
//私有化构造方法
private Boss(String name, int age){
this.name = name;
this.age = age;
}
//私有静态本类对象作为属性
private static Boss boss = new Boss("马云",12);
//提供共有静态方法获取本类对象
public static Boss getBoss(){
return boss;
}
}
懒汉式实现代码
pulbic class King{
//属性
private String name;
private int age;
//私有构造方法
private King(String name, int age){
this.name = name;
this.age = age;
}
//私有静态本类对象
private static King king;
//共有静态方法获取本类对象
public static King getKing(){
if(king==null){
king = new King("唐太宗",12);
}
return king;
}
}
思考:懒汉式和饿汉式有什么区别?
语法区别:懒汉是调用方法时初始化对象,饿汉是声明同时初始化
存储空间:在第一次获取单例类对象前,懒汉比饿汉节省空间
多线程操作时区别:懒汉式存在线程安全问题,饿汉式没有线程安全问题
多线程单例模式
由于饿汉式没有线程安全问题,这里就不再演示,主要讲解一下懒汉式。
2.1懒汉式
实现代码:
/**
* 单例
*
*/
public class SingleTon {
private SingleTon(){
//禁止反射破解
synchronized (SingleTon.class) {
if (instance != null) {
throw new RuntimeException("不能使用反射创建对象");
}
}
}
private static volatile SingleTon instance; //volatile:不稳定的,易挥发的
public static SingleTon getInstance() {
if(singleTon==null) {//为了提高效率
synchronized (SingleTon.class) {//判断锁的过程比较耗性能,为了提高效率
if (singleTon == null) {
singleTon = new SingleTon();
}
}
}
return singleTon;
}
}
/**
* 线程类
* @author wgy
*
*/
public class SingleTonThread extends Thread{
@Override
public void run() {
SingleTon singleTon=SingleTon.getInstance();
System.out.println(singleTon.hashCode());
}
}
package com.qf.day20_6;
public class Test {
public static void main(String[] args) {
//线程对象
SingleTonThread s1=new SingleTonThread();
SingleTonThread s2=new SingleTonThread();
SingleTonThread s3=new SingleTonThread();
//启动线程
s1.start();
s2.start();
s3.start();
}
}
其他方式实现单例模式
3.1静态内部类写法
/*
* 静态内部类写法
* (1)节省空间
* (2)不会线程安全问题
*/
public class SingleTon2 {
private SingleTon2(){
}
static class Holder{
private static final SingleTon2 INSTACNE=new SingleTon2();
}
public static SingleTon2 getInstance(){
return Holder.INSTACNE;
}
}
优点:
(1)节省空间 (2)不会线程安全问题
3.2枚举方式
/*
* 枚举写法
* (1)没有线程安全问题
* (2)反射破解问题
*
*/
public enum SingleTon3 {
INSTANCE;
public static SingleTon3 getInstance(){
return INSTANCE;
}
}
优点:
- (1)没有线程安全问题
- (2)反射破解问题