1、饿汉式
public class Hungry {
private Hungry(){
}
public final static Hungry hungry = new Hungry();
public static Hungry getHungry(){
return hungry;
}
}
2、懒汉式
1)基本的懒汉式
public class Lazy {
private Lazy(){
System.out.println(Thread.currentThread().getName() + "lazy线程启动");
}
if (lazy!=null){
throw new RuntimeException("不要试图用凡是破坏单例!");
}
private static Lazy lazy;
public static Lazy getLazy(){
if (lazy==null){
lazy = new Lazy();
}
return lazy;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
lazy.getLazy();
}).start();
}
}
}
2)解决多线程不安全加双重检测锁
public class Lazy {
private Lazy(){
System.out.println(Thread.currentThread().getName() + "lazy线程启动");
}
private static Lazy lazy;
public static Lazy getLazy(){
if (lazy==null){
synchronized (Lazy.class){
if (lazy==null){
lazy = new Lazy();
}
}
}
return lazy;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
lazy.getLazy();
}).start();
}
}
}
3)针对懒汉式在创建对象时,不是原子性操作,避免指令重排,将属性定义为volatile类型(双重检测锁+原子操作)
public class Lazy {
private Lazy(){
System.out.println(Thread.currentThread().getName() + "lazy线程启动");
}
private volatile static Lazy lazy;
public static Lazy getLazy(){
if (lazy==null){
synchronized (Lazy.class){
if (lazy==null){
lazy = new Lazy();
}
}
}
return lazy;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
lazy.getLazy();
}).start();
}
}
}
4)初步解决反射破坏懒汉式(三重检测)
public class Lazy {
private Lazy(){
synchronized (Lazy.class){
if (lazy!=null){
throw new RuntimeException("不要试图用凡是破坏单例!");
}
}
}
private volatile static Lazy lazy;
public static Lazy getLazy(){
if (lazy==null){
synchronized (Lazy.class){
if (lazy==null){
lazy = new Lazy();
}
}
}
return lazy;
}
public static void main(String[] args) throws Exception {
Lazy instant = lazy.getLazy();
Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
Lazy lazy = declaredConstructor.newInstance();
System.out.println(instant.hashCode());
System.out.println(lazy.hashCode());
}
}
5)如果两个对象都是用单例创建的,通过红绿灯解决
public class Lazy {
private static boolean bool = false;
private Lazy(){
synchronized (Lazy.class){
if (!bool){
bool = true;
}else{
throw new RuntimeException("不要试图用凡是破坏单例!");
}
}
}
private volatile static Lazy lazy;
public static Lazy getLazy(){
if (lazy==null){
synchronized (Lazy.class){
if (lazy==null){
lazy = new Lazy();
}
}
}
return lazy;
}
public static void main(String[] args) throws Exception {
Lazy instant = lazy.getLazy();
Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
Lazy lazy = declaredConstructor.newInstance();
Lazy lazy2 = declaredConstructor.newInstance();
System.out.println(lazy.hashCode());
System.out.println(lazy2.hashCode());
}
}
6)如果红绿灯标志被反射获取,用枚举解决
public class Lazy {
private static boolean bool = false;
private Lazy(){
synchronized (Lazy.class){
if (!bool){
bool = true;
}else{
throw new RuntimeException("不要试图用凡是破坏单例!");
}
}
}
private volatile static Lazy lazy;
public static Lazy getLazy(){
if (lazy==null){
synchronized (Lazy.class){
if (lazy==null){
lazy = new Lazy();
}
}
}
return lazy;
}
public static void main(String[] args) throws Exception {
Lazy instant = lazy.getLazy();
Field bool = Lazy.class.getDeclaredField("bool");
bool.setAccessible(true);
Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
Lazy lazy = declaredConstructor.newInstance();
bool.set(instant,false);
Lazy lazy2 = declaredConstructor.newInstance();
System.out.println(instant.hashCode());
System.out.println(lazy.hashCode());
System.out.println(lazy2.hashCode());
}
}
3、静态内部类实现
public class Holder {
private Holder(){
}
private static Holder getHolder(){
return InnerClass.holder;
}
public static class InnerClass{
private final static Holder holder = new Holder();
}
}
4、枚举
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
public static void main(String[] args) throws Exception {
EnumSingle e1 = EnumSingle.INSTANCE;
Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);
EnumSingle enumSingle = declaredConstructor.newInstance();
System.out.println(e1);
System.out.println(enumSingle);
}
}