前言
单例模式是日常开发中最常见的一种设计模式,常用来做为池对象,或者计数器之类的需要保证全局唯一的场景。
单例模式的目的是保证在整个程序中只存在一个对象实例,使用单例一个前提条件就是构造器私有化,不允许通过new 对象的方式。单例模式的实现主要方式有如下几种:
1、饿汉式实现
2、使用枚举类实现
3、懒汉式使用双重检查锁实现。
4、使用静态内部类实现
“饿汉式”
饿汉式:顾名思义就是很"饥饿",初始化就创建设好了实例。
public class Demo1 {
private static Demo1 demo1 = new Demo1();
private void Demo1() {
}
public static Demo1 getInstance() {
return demo1;
}
}
“懒汉式” -双重检查锁
为什么要使用双重检查锁?因为如果在并发的状态下,如果A线程先进来,判断demo2为null,然后创建实例对象,在判断了为null的这个时间点,B线程也进来了判断demo2为null,也去创建实例,这样就不能保证单例。
public class Demo2 {
private volatile static Demo2 demo2 = null;
private void Demo2() {
}
public static Demo2 getInstance() {
if (demo2 == null) {
synchronized(Demo2.class) {
if (demo2 == null) {
demo2 = new Demo2();
}
}
}
return demo2;
}
}
“懒汉式” -使用静态内部类的方式实现
使用静态内部类的方式实现的单例式利用了java的特性,就是static属于类,在初始化的时候就已经执行了,且static修饰的对象或者静态代码块只执行一次。
public class Demo3 {
private static Demo3 demo3;
private void Demo3() {
}
private static class HolderClass {
private static Demo3 demo3 = new Demo3();
}
public static Demo3 getInstance() {
return HolderClass.demo3;
}
}
枚举方式
枚举方式利用了枚举的特性,enum修饰的类被称之为枚举类,java不允许通过反射来创建enum类,同时enum修饰的类默认继承了Enum类,其构造函数为private修饰的,因此枚举类具有天然的单例特性,很适合用做单例模式。文章来源:https://www.toymoban.com/news/detail-430186.html
public class Demo4 {
private Demo4() {
}
public static enum SingleEnum {
INSTANCE;
private Demo4 demo4;
private SingleEnum() {
demo4 = new Demo4();
}
public Demo4 getInstance() {
return demo4;
}
}
public static Demo4 getInstance() {
return SingleEnum.INSTANCE.getInstance();
}
// 测试
public static void main(String[] args) {
Demo4 instance = getInstance();
}
}
下面来看一个单例模式的典型应用场景:
JefLogTail采集工具中的server端,在处理日志多线程入库时,为了防止反复的创建线程池导致服务器压力大,因此采用单例模式来定义线程池的获取。如下:文章来源地址https://www.toymoban.com/news/detail-430186.html
public class LogHandle extends ServerMessageHandler {
private LogSave logSave;
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Message message) throws Exception {
try {
/* String content = (String) message.getContent();
String ip = message.getAttachment("ip");
String fileName = message.getAttachment("fileName");
System.out.println("ip地址:" + ip);
System.out.println("文件名称:" + fileName);*/
ThreadPoolCfg.getThreadPool().execute(new Runnable() {
@Override
public void run() {
logSave.save(message);
}
});
// 多线程处理
} catch (Exception e) {
e.printStackTrace();
}
}
public void setLogSavePlan(LogSave logSave) {
this.logSave = logSave;
}
}
到了这里,关于单例模式的四种创建方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!