Java教程

java单例设计模式

本文主要是介绍java单例设计模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

饿汉式:

直接实例化饿汉式(简介直观)

package test;

/**
 * 饿汉式:
 * 		直接创建实例对象,不管你是否需要这个对象都会创建
 * 1.构造器私有化
 * 2.自行创建,并且用静态变量保存
 * 3.向外提供这个实例
 * 4.强调这是一个单例,我们可以用final修饰
 * @author asus
 *
 */
public class Singleton1 {
	public static final Singleton1 INSTANCE = new Singleton1();
	private Singleton1() {
		
	}
}

枚举式(最简洁)

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

静态代码块饿汉式(适合复杂实例化)

package test;

public class Singleton3 {
	public static final Singleton3 INSTANCE;
	static {
		INSTANCE=new Singleton3();
	}
	private Singleton3() {
		
	}
}

懒汉式:

package test;
/**
 * 懒汉式:
 * 		延迟创建这个实例对象
 * 1.构造器私有化
 * 2.用一个静态变量保存这个唯一的实例
 * 3.提供一个静态方法,获取这个实例对象
 * @author asus
 *
 */
public class Singlenton4 {
	private static Singlenton4 instance;
	private Singlenton4() {
		
	}
	public static Singlenton4 getInstance() {
		if(instance==null) {
			instance=new Singlenton4();
		}
		return instance;
	}
}

发现有线程安全问题
在这里插入图片描述

package test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestSingleton4 {
	public static void main(String[] args)throws Exception {
		/*Singlenton4 s1=Singlenton4.getInstance();
		Singlenton4 s2=Singlenton4.getInstance();
		System.out.println(s1==s2);
		System.out.println(s1);
		System.out.println(s2);*/
		Callable<Singlenton4> c= new Callable<Singlenton4>() {
			@Override
			public Singlenton4 call() throws Exception{
				return Singlenton4.getInstance();
			}
		};
		ExecutorService	es=Executors.newFixedThreadPool(2);
		Future<Singlenton4>f1=es.submit(c);
		Future<Singlenton4>f2=es.submit(c);
		Singlenton4 s1= f1.get();
		Singlenton4 s2= f1.get();
		System.out.println(s1==s2);
		System.out.println(s1);
		System.out.println(s2);
		
		es.shutdown();
	}
}

在这里插入图片描述
在这里插入图片描述
//代码加锁防止线程问题

package test;

public class Singleton5 {
	private static Singleton5 instance;
	private Singleton5() {
		
	}
	public static Singleton5 getInstance() {
		synchronized (Singleton5.class) {
			if(instance==null) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO: handle exception
					e.printStackTrace();
				}
				instance=new Singleton5();
			}
		}
		return instance;
	}

}

package test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestSingleton4 {
	public static void main(String[] args)throws Exception {
		/*Singlenton4 s1=Singlenton4.getInstance();
		Singlenton4 s2=Singlenton4.getInstance();
		System.out.println(s1==s2);
		System.out.println(s1);
		System.out.println(s2);*/
		Callable<Singleton5> c= new Callable<Singleton5>() {
			@Override
			public Singleton5 call() throws Exception{
				return Singleton5.getInstance();
			}
		};
		ExecutorService	es=Executors.newFixedThreadPool(2);
		Future<Singleton5>f1=es.submit(c);
		Future<Singleton5>f2=es.submit(c);
		Singleton5 s1= f1.get();
		Singleton5 s2= f1.get();
		System.out.println(s1==s2);
		System.out.println(s1);
		System.out.println(s2);
		
		es.shutdown();
	}
}

在这里插入图片描述
加一个if提升效率,只有第一次线程进入时候才加线程锁
在这里插入图片描述
另一种安全简洁的创建方法

package test;
/**
 * 在内部类被加载和初始化时,才创建INSTANCE实例对象。
 * 静态内部类不会自动随着外部类的加载和初始化而初始化,他是要单独去加载和初始化的。
 * 因为是在内部类加载和初始化时创建的,所以是线程安全的的
 * @author asus
 *
 */
public class Singleton6 {
	private Singleton6() {
		
	}
	private static class Inner{
		private static final Singleton6 INSTANCE=new Singleton6();
	}
	public static Singleton6 getInner() {
		return Inner.INSTANCE;
	}
}

如果是饿汉式,枚举形式最简单
如果是懒汉式,静态内部类形式最简单

这篇关于java单例设计模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!