单例模式就是说系统中对于某类的只能有一个对象,不可能出来第二个。
单例模式也是23中设计模式中在面试时少数几个会要求写代码的模式之一。主要考察的是多线程下面单例模式的线程安全性问题。
1.多线程安全-单例模式实例一(不使用同步锁)
package singleton_test;
/**
* 1.多线程安全单例模式实例一(不使用同步锁)
* @author x1c
*
*/
public class Singleton {
private static Singleton sin = new Singleton(); //直接初始化一个实例对象
private Singleton(){
}
public static Singleton getSign() {
return sin;
}
public static void main(String[] args) {
for (int i = 0; i <10; i++) {
System.out.println(Singleton.getSign());
}
}
}
上述代码中的一个缺点是该类加载的时候就会直接new 一个静态对象出来,当系统中这样的类较多时,会使得启动速度变慢 。现在流行的设计都是讲“延迟加载”,我们可以在第一次使用的时候才初始化第一个该类对象。所以这种适合在小系统。
2.多线程安全-单例模式实例二(使用同步方法)
package singleton_test;
/**
* 2.多线程安全单例模式实例二(使用同步方法)
* @author x1c
*
*/
public class Singleton2 {
private static Singleton2 instance; //加载时不用new
private Singleton2(){
}
public static synchronized Singleton2 getInstance() { //对获取实例的方法进行同步
if (instance == null) {
instance = new Singleton2(); //需要时再new出来
}
return instance;
}
public static void main(String[] args) {
for (int i = 0; i <10; i++) {
System.out.println(Singleton2.getInstance());
}
}
}
上述代码中的一次锁住了一个方法, 这个粒度有点大 ,改进就是只锁住其中的new语句就OK。就是所谓的“双重锁”机制。
3.多线程安全-单例模式实例三(使用双重同步锁)
package singleton_test;
/**
* 3.多线程安全单例模式实例三(使用双重同步锁)
* 执行过程:
1.先判断是否有student实例,如果有,返回实例
2.如果第一次执行这个方法,是没有实例的,这时进入if
通过synchronized块控制了同步,虽然会造成性能下降,
但是只有第一次初始对象时会这样
* @author x1c
*
*/
public class Singleton3 {
private static Singleton3 instance; //加载时不用new
private Singleton3(){
}
public static Singleton3 getInstance() { //不对获取实例的方法进行同步
if (instance == null) {
synchronized (Singleton3.class) {
if (instance == null) {
instance = new Singleton3();
}
}
}
return instance;
}
public static void main(String[] args) {
for (int i = 0; i <10; i++) {
System.out.println(Singleton3.getInstance());
}
}
}
以上参考地址:
https://www.cnblogs.com/xudong-bupt/p/3433643.html
-------------------------------------------------------------------------------
4.多线程安全-单例模式实例四(内部类)
较好的方式:既不用加锁,也能实现懒加载
package singleton_test;
/**
* 单例模式
* 4. 不用加锁,也能实现懒加载
* @author x1c
*
*/
public class Singleton4 {
private Singleton4(){
System.out.println("construct method:single()");
}
//内部类
private static class Innner {
private static Singleton4 instance = new Singleton4();
}
//获取单例对象
public static Singleton4 getInstance() {
return Innner.instance;
}
public static void main(String[] args) {
for (int i = 0; i <10; i++) {
System.out.println(Singleton4.getInstance());
}
}
}
---------------------------------------------------------
5.多线程安全-单例模式实例四(枚举)
单例的枚举实现在《Effective Java》中有提到,
因为其功能完整、使用简洁、无偿地提供了序列化机制、
在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点,
单元素的枚举类型被作者认为是实现Singleton的最佳方法
package singleton_test;
/**
* 枚举实现单例
* @author x1c
*
*/
public class Singleton5 {
}
package singleton_test;
/**
* 单例模式
* 使用枚举方式实现:
* 单例的枚举实现在《Effective Java》中有提到,
* 因为其功能完整、使用简洁、无偿地提供了序列化机制、
* 在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点,
* 单元素的枚举类型被作者认为是实现Singleton的最佳方法
* @author x1c
*
*/
public enum Singleton5Enum {
INSTANCE;
private Singleton5 intance = null;
private Singleton5Enum() {
intance = new Singleton5();
}
public Singleton5 getInstance() {
return intance;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(Singleton5Enum.INSTANCE.getInstance());
}
).start();
}
}
}
枚举实现单例参考:https://blog.csdn.net/gavin_dyson/article/details/70832185
--------------------------------------------------------------
end;