单例模式保证来到对象在内存中保证唯一
public class Singleton{ private static final Singleton singleObject = new Singleton(); private Singleton(){} public static getSingleton(){ return singleObject; } }
饿汉模式在第一次引用该类的时候就创建对象实例。
饱汉模式
public class Singleton{ private static Singleton singleObject = null; private Singleton(){} public static getSingleton(){ if(singleObject == null){ singleObject = new Singleton; } return singleObject; } }
双重锁模式
//这种方式只考虑到线程安全,但每次调用getSingleton()方法 //都必须在synchornized进行排队 public class Singleton{ private static Singleton singleObject = null; private Singleton(){} public static getSingleton(){ synchronized(Singleton.class){ if(singleObject == null){ singleObject = new Singleton; }
} return singleObject; } }
改进之后的
//先进行判断是否已存在对象,如无进入线程等待 //已存在对象就只需要返回,不需要线程等待 public class Singleton{ private static volatile Singleton singleObject = null; private Singleton(){} public static getSingleton(){ if(singleObject == null){ synchronized(Singleton.class){ if(singleObject == null){ singleObject = new Singleton; } } return singleObject; } } }
几种模式的比较:
1、饿汉模式是线程安全的,因为实例对象在类加载过程中就会被创建,在getInstance()方法中只是直接返回对象引用。
好处:无需关注线程安全问题。
缺点:如果在一个大环境下使用了过多的饿汉单例,则会生产出过多的实例对象。
2、饱汉模式不是线程安全的,因为是在需要的时候才会产生实例对象,生产之前会判断对象引用是否为空,这里,如果多个线程同时进入判断,就会生成多个实例对象,这是不符合单例的思想的。所以饱汉模式为了保证线程安全,就用synchronized关键字标识了方法。之所以被称为“饱汉”,因为它很饱,不急着生产实例,在需要的时候才会生产。
好处:延时加载,用的时候才会生产对象。
缺点:需要保证同步,付出效率的代价。
3、双重锁模式,是饱汉模式的优化,进行双重判断,当已经创建过实例对象后就无需加锁,提高效率。
枚举写法单例模式
public enum EnumSingleton{ singleObject; private String name; public String getName(){ return name; } public void setName(String name){ this.name = name; } }
Lambda表达式
//创建线程 Thread td = new Thread(new Runnable){ public void run(){ System.out.println("---"); } }; td.start(); //表达式 Thread td = new Thread(() -> System.out.println("---")); td.start(); //排序 List<String> list = Arrays.asList(new String[]{"a", "b", "c"}); Collections.sort(list, new Comparator<String>){ public int compare(String str1, String str2){ return str1.conpareTo(str2); } }); //表达式 Collections.sort(list, (str1, str2) -> str1.compareTo(str2));
当使用Lambda表达式替代内部类创建对象时,Lambda表示的代码块将会代替实现抽象方法的方法体,Lambda表达式就相当于一个匿名方法。
形参列表:形参列表允许省略形参类型。如果形参列表只有一个参数,甚至连形参列表的圆括号都可以省略。
箭头 ->必须通过英文中线和大于符号组成
代码块,如果代码块只有一条语句,允许省略代码块的花括号。Lambada代码块只有一条return语句,甚至可以省略return关键字。Lambda需要返回值,儿它的代码块省略了return关键字,会自动返回这条语句的值。
public class LambdaClass2{ public void Method1(InterfaceClass1 inClass1){ //System.out.println(inClass1); inClass1.InterfaceClass1Method(); } public void Method2(InterfaceClass2 inClass2){ inClass2.InterfaceClass2Method("适合出游"); } public void Method3(InterfaceClass3 inClass3){ //inClass3.InterfaceClass3Method(5, 3); System.out.println(inClass3.InterfaceClass3Method(5, 3)); } public static void main(String[] args){ LambdaClass2 lc = new LambdaClass2(); //如果只有一个语句可以省略花括号 lc.Method1(() -> System.out.println("这是一个苹果")); //Lambda只有一个形参,可以省略圆括号 lc.Method2(str -> { System.out.println("天气不错" + str); System.out.println("雨夹雪"); }); //代码块中只有一条语句,即使该表达式需要返回值,也可以省略return关键字 lc.Method3((a, b) -> a + b); } } interface InterfaceClass1{ void InterfaceClass1Method(); } interface InterfaceClass2{ void InterfaceClass2Method(String str); } interface InterfaceClass3{ int InterfaceClass3Method(int a, int b); }