终于理解单列模式了,单列模式和多线程
2018年03月22日 11:09:45 一只不会飞的菜鸟 阅读数:278更多
个人分类: Java核心基础
//1、单例类确保自己只有一个实例(构造方法私有化)
//2、单例类必须自己创建自己的实例。
//3、单例类必须为其他对象提供唯一的实例。
package Singleton;
//懒汉式 单例实例在第一次被使用时构建,延迟初始化。
public class singleton {
private static singleton sing =null; //1,表明这个类是不可能形成实例了。这主要是怕这个类会有多个实例。
public static singleton getInstance(){ //2,即然这个类是不可能形成实例,那么,我们需要一个静态的方式让其形成实例:getInstance()
if(sing==null){ //3,在getInstance()中,先做判断是否已形成实例,如果已形成则直接返回,否则创建实例, 我们取实例时,只需要使用Singleton.getInstance()就行了。
synchronized(singleton.class){//线程同步锁,必须等一个线程访问完,才能进行访问
if(sing==null){//需要双重锁定,保证不会new两次
sing=new singleton();//懒汉式:先初始化实例对象
}
}
}
return sing;
}
public void getName() {// 使用普通方法输出皇帝的名字
System.out.println("单列模式:懒汉式");
}
}
//优点: 避免了饿汉式的那种在没有用到的情况下创建事例,资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法。
//缺点: 懒汉式在单个线程中没有问题,但多个线程同事访问的时候就可能同事创建多个实例,而且这多个实例不是同一个对象,虽然后面创建的实例会覆盖先创建的实例,但是还是会存在拿到不同对象的情况。解决这个问题的办法就是加锁synchonized,第一次加载时不够快,多线程使用不必要的同步开销大。
//饿汉式 在自己内部定义自己的一个实例,只供内部调用
public class Singleton1
{
//2.提供一个全局访问点(其实就是一个全局静态字段),外部可以通过该字段访问该类的唯一实例
//因为静态字段是属于类的,所以这样可以保证只有一个实例。
private static final Singleton1 only = new Singleton1();//单例实例在类装载时就构建,急切初始化
//1 将构造函数声明成私有的,这样可以确保在类的外部无法实例化该类(即在类的外部获取不到类的实例)
private Singleton1() {//私有(private)的构造函数,表明这个类是不可能形成实例了, 解释:一个对象默认是存在一个隐式的带无参的构造方法,默认是public,所以在new一个对象时,默认调用的隐式的构造函数,当构造函数私有时就不能实例化对象。构造方法作用初始化,方法名和类名一样。创建对象都通过new
//do something
}
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton1 getInstance(){// 实例化引用
return only;
}
//测试用方法
public void put(){
System.out.println("单列模式:饿汉式");
}
//优点 1.线程安全
// 2.在类加载的同时已经创建好一个静态对象,调用时反应速度快
//缺点
// 资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化
}
public class test {
public static void main(String[] args) {
//将entry类的构造函数声明为私有的构造函数,这样我们在外部就无法通过Singleton s = new Singleton()来实例化该,因为Private生命的成员只有在该类的内部可以访问。这样可以保证类的实例只有一个(那就是在类的内部给它实例化)。
singleton sing = singleton.getInstance();
singleton sing1 = singleton.getInstance();
System.out.println(sing.equals(sing1));//指向同一个对像
sing.getName();//懒汉式实例对象输出
sing1.getName();
System.out.println("-----------------------------------------");
Singleton1 s = Singleton1.getInstance();
Singleton1 s1 = Singleton1.getInstance();
s.put();//饿汉式实例对象输出
s1.put();
System.out.println(s.equals(s1));//指向同一个对像
}