单例模式
1.基本介绍
1.1定义与类型
定义:保证一个类仅有一个实例,并提供一个全局访问点
类型:创建型
1.2 单例-适用场景
想确保任何情况下都绝对只有一个实例
单服务-计数器 线程池-设计 -链接池
1.3 优点和缺点
在内存中只有一个实例,减少内存开销
可以避免资源的多重占用
严格控制访问
缺点:
没有接口,扩展困难
1.4 多线程debug
all:本线程的断点
thread:控制线程执行的顺序,会一直等待来处理它。
makedefault:
1.5 懒汉式实现和多线程问题处理
懒汉式实现的会出现多线程问题
/**
* 懒汉式
* 1.静态的单例对象
* 2.构造函数私有化
* 3.懒汉式延迟加载,需要使用的时候才加载
*/
public class LazySingleton {
private static LazySingleton lazySingleton=null;
private LazySingleton(){
}
/**
* 线程不安全,多线程读时候,第一个线程
* @return
*/
public static LazySingleton getInstance(){
if(lazySingleton==null){
lazySingleton=new LazySingleton();
}
return lazySingleton;
}
}
public class T implements Runnable{
public void run() {
LazySingleton lazySingleton=LazySingleton.getInstance();
System.out.println(Thread.currentThread().getName()+"--"+lazySingleton);
}
}
public class Test {
public static void main(String[] args) {
// LazySingleton lazySingleton=LazySingleton.getInstance();
Thread t1=new Thread(new T());
Thread t2=new Thread(new T());
t1.start();
t2.start();
//多线程debug
System.out.println();
}
}
对于上面在上面的多线程的问题处理:
1.加锁在方法上。同步方法。类的class文件。锁了这个类。性能消耗大
/**
* 线程不安全,多线程读时候,第一个线程
* @return
*/
public synchronized static LazySingleton getInstance(){
if(lazySingleton==null){
lazySingleton=new LazySingleton();
}
return lazySingleton;
}
2.double check
public class T implements Runnable{
public void run() {
// LazySingleton lazySingleton=LazySingleton.getInstance();
LazyDoubleCheckSingleton lazyDoubleCheckSingleton=LazyDoubleCheckSingleton.getInstance();
System.out.println(Thread.currentThread().getName()+"--"+lazyDoubleCheckSingleton);
}
}
public class LazyDoubleCheckSingleton {
//volatile 防止重排序
private volatile static LazyDoubleCheckSingleton lazySingleton=null;
private LazyDoubleCheckSingleton (){
}
/**
* 线程不安全,多线程读时候,第一个线程
* @return
*/
public static LazyDoubleCheckSingleton getInstance(){
if(lazySingleton==null){
synchronized (LazyDoubleCheckSingleton.class){
if(lazySingleton==null){
lazySingleton=new LazyDoubleCheckSingleton();
//1.分配内存给这个对象
//2.初始化对象
//存在指令重排序。
//3.设置lazyDoubleCheckSigleton 指向内存地址
}
}
}
return lazySingleton;
}
}
1.6 饿汉式:
/**
* 饿汉式,类加载就完成初始化,线程没有同步问题。
*/
public class HungrySingleton {
private final static HungrySingleton hungrySingleton;
static {
hungrySingleton=new HungrySingleton();
}
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
1.7 序列化和反序列化破坏单例
/**
* 饿汉式,类加载就完成初始化,线程没有同步问题。
*/
public class HungrySingleton implements Serializable {
private final static HungrySingleton hungrySingleton;
static {
hungrySingleton=new HungrySingleton();
}
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
private Object readResolve(){
return hungrySingleton;
}
}
public class Test {
public static void main(String[] args) throws Exception {
HungrySingleton instance = HungrySingleton.getInstance();
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("singletonfile"));
oos.writeObject(instance);
File file=new File("singletonfile");
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file));
HungrySingleton newInstance= (HungrySingleton) ois.readObject();
System.out.println(instance==newInstance);
}
}
2.JDK 源码实战
Runtime
public class Runtime {
private static Runtime currentRuntime = new Runtime();
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class <code>Runtime</code> are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the <code>Runtime</code> object associated with the current
* Java application.
*/
public static Runtime getRuntime() {
return currentRuntime;
}