一、概念

所谓单例模式,就是采取一定的方法保证整个系统中,对某个类只能存在一个对象实例,并且该类只对外提供一个获取该对象实例的方法。

分类:单例模式一共有八种写法,分别为:

  • 饿汉式 - 静态常量方式;
  • 饿汉式 - 静态代码块;
  • 懒汉式 - 线程不安全方式;
  • 懒汉式 - 线程安全 - 同步方法方式;
  • 懒汉式 - 线程安全 - 同步代码块;
  • 双重检查(Double Check);
  • 静态内部类;
  • 枚举单例;

下面将通过示例分别对各种实现方式进行总结。

二、单例模式

【a】饿汉式 - 静态常量方式

(1). 实现代码:

package com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern01;/*** @Description: 单例模式第一种写法:饿汉式 - 静态常量方式* @author: weixiaohuai* @Date: 2019/10/17 14:49* <p>* 说明:* 饿汉式 - 静态常量方式:* 优点: 写法简单,在类装载的时候就完成实例化,避免了线程同步问题。* 缺点: 在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。* 综上所述: 饿汉式 - 静态常量方式只能说是可用,毕竟还不是最佳写法。*/
public class SingletonPattern01 {public static void main(String[] args) {Singleton singleton = Singleton.getInstance();//com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern01.Singleton@4f023edbSystem.out.println(singleton);Singleton singleton1 = Singleton.getInstance();//com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern01.Singleton@4f023edbSystem.out.println(singleton1);//可见,获取的两个实例地址是一样。}}class Singleton {/*** 第一步: 定义一个Singleton常量对象*/private static final Singleton INSTANCE = new Singleton();/*** 第二步: 构造方法私有化,其他类就无法构造Singleton实例*/private Singleton() {}/*** 第三步: 对外提供一个获得该实例的静态方法*/public static Singleton getInstance() {return INSTANCE;}
}

(2). 运行结果:

由图可见,两个实例的地址一样,说明确实是保证了只能有一个实例存在。

  • (3). 总结: 此种方式可用,但是可能造成内存浪费。
  • 优点: 写法比较简单,在类装载的时候就完成实例化,避免了线程同步问题。
  • 缺点: 因为在类装载的时候就完成实例化,没有达到懒加载的效果。如果从始至终都没有使用这个实例,则会造成内存浪费问题。

【b】饿汉式 - 静态代码块

(1). 实现代码:

package com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern02;/*** @Description: 单例模式第二种写法:饿汉式 - 静态代码块初始化方式* @author: weixiaohuai* @Date: 2019/10/17 14:49* <p>* 说明:* 饿汉式 - 静态代码块初始化方式:* 优点: 写法简单,在类装载的时候就完成实例化,避免了线程同步问题。* 缺点: 在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。* 综上所述: 饿汉式 - 静态代码块初始化方式跟前面的静态常量方式差不多,优缺点都一样,只不过在静态代码块中进行初始化而已,所以也只能说是可用,毕竟还不是最佳写法。*/
public class SingletonPattern02 {public static void main(String[] args) {Singleton singleton = Singleton.getInstance();//com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern02.Singleton@4f023edbSystem.out.println(singleton);Singleton singleton1 = Singleton.getInstance();//com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern02.Singleton@4f023edbSystem.out.println(singleton1);//可见,获取的两个实例地址是一样。}}class Singleton {/*** 第一步: 定义一个Singleton对象*/private static Singleton instance;/*** 第二步: 构造方法私有化,其他类就无法构造Singleton实例*/private Singleton() {}/*** 第三步: 静态代码块中初始化Singleton实例*/static {//在类装载的时候,执行静态代码块,完成实例化instance = new Singleton();}/*** 第四步: 对外提供一个获得该实例的方法*/public static Singleton getInstance() {return instance;}
}

(2). 运行结果:

可见,两个实例的地址也一致。

  • (3). 总结:此种方式跟饿汉式-静态常量方式基本一致,只是初始化实例的地方不一样,优缺点都一致。
  • 优点: 写法比较简单,在类装载的时候就完成实例化,避免了线程同步问题。
  • 缺点: 因为在类装载的时候就完成实例化,没有达到懒加载的效果。如果从始至终都没有使用这个实例,则会造成内存浪费问题。

【c】懒汉式 - 线程不安全方式

(1). 实现代码:

/*** @Description: 单例模式第三种写法:懒汉式 - 线程不安全方式* @author: weixiaohuai* @Date: 2019/10/17 14:49* <p>* 说明:* 懒汉式 - 线程不安全方式:* 优点: 支持Lazy Loading懒加载,但是只能在单线程下使用* 缺点: 在多线程下,一个线程进入了判断实例是否为空,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。* 综上所述: 在实际工作中,不能使用该方式,可能会破坏单例模式。*/
public class SingletonPattern03 {public static void main(String[] args) {Singleton singleton = Singleton.getInstance();//com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern03.Singleton@4f023edbSystem.out.println(singleton);Singleton singleton1 = Singleton.getInstance();//com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern03.Singleton@4f023edbSystem.out.println(singleton1);//可见,获取的两个实例地址是一样。}}class Singleton {/*** 第一步: 定义一个Singleton对象*/private static Singleton instance;/*** 第二步: 构造方法私有化,其他类就无法构造Singleton实例*/private Singleton() {}/*** 第三步: 对外提供一个获得该实例的方法,首先判断是否存在单例实例,不存在的时候才去new对象.* 注意:多个线程同时进来的话,都进行判断,如果同时判断为空,那么会造成new了多个实例,所以只能单线程使用。*/public static Singleton getInstance() {if (null == instance) {instance = new Singleton();}return instance;}
}

(2). 运行结果:

可见,两个实例的地址是一样的,但是这种方式在多线程环境下是有问题的,可能会造成多创建实例的情况,具体看下面的代码:

(3). 模拟多线程环境:验证两个实例地址是否还能保持一致?

public class SingletonPattern03 {public static void main(String[] args) {
//        Singleton singleton = Singleton.getInstance();
//        //com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern03.Singleton@4f023edb
//        System.out.println(singleton);
//        Singleton singleton1 = Singleton.getInstance();
//        //com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern03.Singleton@4f023edb
//        System.out.println(singleton1);
//        //可见,获取的两个实例地址是一样。Thread t1 = new Thread(new Thread01());Thread t2 = new Thread(new Thread02());t1.start();t2.start();}}class Singleton {/*** 第一步: 定义一个Singleton对象*/private static Singleton instance;/*** 第二步: 构造方法私有化,其他类就无法构造Singleton实例*/private Singleton() {}/*** 第三步: 对外提供一个获得该实例的方法,首先判断是否存在单例实例,不存在的时候才去new对象.* 注意:多个线程同时进来的话,都进行判断,如果同时判断为空,那么会造成new了多个实例,所以只能单线程使用。*/public static Singleton getInstance() {if (null == instance) {instance = new Singleton();}return instance;}
}class Thread01 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread01-->" + singleton);}
}class Thread02 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread02-->" + singleton);}
}

可见,在多线程下,有可能会发生两个实例地址不一致的情况,这样就不能保证单例了。

  • (4). 总结:在实际工作中,不能使用该方式,可能会破坏单例模式。
  • 优点: 支持Lazy Loading懒加载,但是只能在单线程下使用
  • 缺点: 在多线程下,一个线程进入了判断实例是否为空,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。

【d】懒汉式 - 线程安全 - 同步方法方式

(1). 实现代码:

package com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern04;/*** @Description: 单例模式第四种写法:懒汉式 - 线程安全 - 同步方法方式* @author: weixiaohuai* @Date: 2019/10/17 14:49* <p>* 说明:* 懒汉式 - 线程安全 - 同步方法方式方式:* 优点: 解决了上面一种写法在多线程环境下会new多实例的情况* 缺点: 效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。方法进行同步效率太低要改进。* 综上所述: 该种方式不推荐使用*/
public class SingletonPattern04 {public static void main(String[] args) {Singleton singleton = Singleton.getInstance();System.out.println(singleton);Singleton singleton1 = Singleton.getInstance();  System.out.println(singleton1);//可见,获取的两个实例地址是一样。Thread t1 = new Thread(new Thread01());Thread t2 = new Thread(new Thread02());t1.start();t2.start();}}class Singleton {/*** 第一步: 定义一个Singleton对象*/private static Singleton instance;/*** 第二步: 构造方法私有化,其他类就无法构造Singleton实例*/private Singleton() {}/*** 第三步: 对外提供一个获得该实例的方法* 注意:每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步*/public synchronized static Singleton getInstance() {if (null == instance) {instance = new Singleton();}return instance;}
}class Thread01 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread01-->" + singleton);}
}class Thread02 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread02-->" + singleton);}
}

(2). 运行结果:

可见,两个实例的地址确实是一样,但是此种方式锁住整个getInstance()方法,每个线程想获取实例的时候都需要在方法外面等待,效率不好,不推荐使用。

  • (3). 总结:
  • 优点: 解决了上面一种写法在多线程环境下会new多实例的情况
  • 缺点: 效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。方法进行同步效率太低要改进。

【e】懒汉式 - 线程安全 - 同步代码块

(1). 实现代码:

package com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern05;/*** @Description: 单例模式第五种写法:懒汉式 - 线程安全 - 同步代码块* @author: weixiaohuai* @Date: 2019/10/17 14:49* <p>* 说明:* 懒汉式 - 线程安全 - 同步代码块方式:* 由于第四种实现方式同步效率太低,所以摒弃同步方法,改为同步产生实例化的的代码块。但是这种同步并不能起到线程同步的作用。跟第3种实现方式遇到的情形一致,假如一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。* 综上所述: 在开发过程不推荐使用该种方式。*/
public class SingletonPattern05 {public static void main(String[] args) {Thread t1 = new Thread(new Thread01());Thread t2 = new Thread(new Thread02());t1.start();t2.start();}}class Singleton {/*** 第一步: 定义一个Singleton对象*/private static Singleton instance;/*** 第二步: 构造方法私有化,其他类就无法构造Singleton实例*/private Singleton() {}/*** 第三步: 对外提供一个获得该实例的方法*/public static Singleton getInstance() {if (null == instance) {synchronized (Singleton.class) {instance = new Singleton();}}return instance;}
}class Thread01 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread01-->" + singleton);}
}class Thread02 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread02-->" + singleton);}
}

(2). 运行结果:

如图,在多线程环境下就存在多new了一个Singleton实例的情况,此方式虽然解决了上面一个方式效率低的问题,但是存在多线程安全问题。假如一个线程进入了if (singleton == null)判断语句块, 还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。

  • (3). 总结:此种方式不推荐使用,会有线程安全问题,破坏单例模式。

【f】双重检查(Double Check)

(1). 实现代码:

package com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern06;/*** @Description: 单例模式第六种写法:双重检查* @author: weixiaohuai* @Date: 2019/10/17 14:49* <p>* 说明:* 双重检查方式:* Double-Check概念对于多线程开发者来说不会陌生,如代码中所示,我们进行了两次if (singleton == null)检查,这样就可以保证线程安全了。这样,实例化代码只用执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象。* <p>* 优点: 线程安全;延迟加载;效率较高。* 缺点:* 综上所述: 该种方式推荐使用*/
public class SingletonPattern06 {public static void main(String[] args) {Thread t1 = new Thread(new Thread01());Thread t2 = new Thread(new Thread02());t1.start();t2.start();}}class Singleton {/*** 第一步: 定义一个Singleton对象* 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。(实现可见性)*/private static volatile Singleton instance;/*** 第二步: 构造方法私有化,其他类就无法构造Singleton实例*/private Singleton() {}/*** 第三步: 对外提供一个获得该实例的方法*/public static Singleton getInstance() {if (null == instance) {// 假设这里已经有多个线程A、B同时进来,假设A先进去判断实例为空,那么A先创建Singleton实例,// 当B进去同步块的时候,由于使用了第二重检查,判断实例已经创建了,所以直接返回A创建好的实例,不会重复创建多个实例。// 线程安全synchronized (Singleton.class) {if (null == instance) {instance = new Singleton();}}}return instance;}
}class Thread01 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread01-->" + singleton);}
}class Thread02 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread02-->" + singleton);}
}

(2). 运行结果:

可见,两个实例的地址一致,并且也实现了懒加载,在多线程环境下, 假设这里已经有多个线程A、B同时进来,假设A先进去判断实例为空,那么A先创建Singleton实例,当B进去同步块的时候,由于使用了第二重检查,判断实例已经创建了,所以直接返回A创建好的实例,不会重复创建多个实例,线程安全。

  • (3). 总结:强烈推荐此种方式实现单例模式。
  • 优点:线程安全;延迟加载;效率较高。

【g】静态内部类

(1). 实现代码:

package com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern07;/*** @Description: 单例模式第七种写法:静态内部类* @author: weixiaohuai* @Date: 2019/10/17 14:49* <p>* 说明:* 这种方式跟饿汉式方式采用的机制类似,但又有不同。两者都是采用了类装载的机制来保证初始化实例时只有一个线程。不同的地方在饿汉式方式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载InnerSingletonInstance类,从而完成Singleton的实例化。* <p>* 类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。* <p>* 优点:避免了线程不安全,延迟加载,效率高。* <p>* 综上所述: 该种方式推荐使用*/
public class SingletonPattern07 {public static void main(String[] args) {Thread t1 = new Thread(new Thread01());Thread t2 = new Thread(new Thread02());t1.start();t2.start();}}class Singleton {/*** 第二步: 构造方法私有化,其他类就无法构造Singleton实例*/private Singleton() {}/*** 第二步: 使用静态内部类,该类有一个静态属性Singleton对象* 当Singleton类被装载时,静态内部类是不会进行装载的。* 只有使用getInstance()方法用到INSTANCE时内部类才会被装载,起到懒加载的效果* 类装载是线程安全的*/private static class InnerSingletonInstance {private static final Singleton INSTANCE = new Singleton();}/*** 第三步: 对外提供一个获得该实例的方法*/public static Singleton getInstance() {return InnerSingletonInstance.INSTANCE;}
}class Thread01 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread01-->" + singleton);}
}class Thread02 implements Runnable {private Singleton singleton;@Overridepublic void run() {singleton = Singleton.getInstance();System.out.println("Thread02-->" + singleton);}
}

(2). 运行结果:

可见,两个实例的地址一致,保证了实例唯一。使用静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载InnerSingletonInstance类,从而完成Singleton的实例化。

  • (3). 总结:JVM帮助我们保证线程的安全性,在类进行初始化时,别的线程是无法进入的。
  • 优点:避免了线程不安全,延迟加载,效率高。

【h】枚举单例

(1). 实现代码:

package com.wsh.springboot.springbootdesignpattern.singletonpattern.singletonpattern08;/*** @Description: 单例模式第八种写法:枚举单例* @author: weixiaohuai* @Date: 2019/10/17 14:49* <p>* 说明:* <p>* 优点: 不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。* 缺点:* 综上所述: 该种方式推荐使用*/
public class SingletonPattern08 {public static void main(String[] args) {SingletonInstance instance1 = Singleton.INSTANCE.getInstance();SingletonInstance instance2 = Singleton.INSTANCE.getInstance();System.out.println(instance1);System.out.println(instance2);}
}/*** 首先,在枚举中我们明确了构造方法限制为私有,在我们访问枚举实例时会执行构造方法,同时每个枚举实例都是static final类型的,也就表明只能被实例化一次。在调用构造方法时,我们的单例被实例化。* 也就是说,因为enum中的实例被保证只会被实例化一次,所以我们的INSTANCE也被保证实例化一次。*/
enum Singleton {/*** 实例*/INSTANCE;private SingletonInstance singletonInstance;/*** 一个enum的构造方法限制是private的,也就是不允许我们调用*/Singleton() {singletonInstance = new SingletonInstance();System.out.println("执行Singleton()构造方法.....");}public SingletonInstance getInstance() {return singletonInstance;}}class SingletonInstance {int i = 0;public SingletonInstance() {System.out.println("SingletonInstance()构造器执行了 " + (++i) + " 次");}
}

(2). 运行结果:

可见,两个实例的地址一致,保证实例唯一。

  • (3). 总结:推荐使用此种方式实现单例,枚举单例在实际项目中比较少用。
  • 优点: 不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。

三、JDK中单例模式的应用示例

在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;}/** Don't let anyone else instantiate this class */private Runtime() {}//........}    

四、总结

单例模式注意事项和使用说明:

  • 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
  • 当想实例化一个单例类的时候,记住使用对外暴露的获取对象实例的方法,而不是使用new,也无法new实例(构造器私有)。

适用场合:

  • 需要频繁创建以及销毁的对象;
  • 创建对象时耗时过多或耗费资源过多(即重量级对象),但又经常用到的对象;
  • 工具类对象;
  • 频繁访问数据库或文件的对象(比如数据源、session工厂等等);

最后,推荐在项目中使用单例实现方式:

  • 双重检查(Double Check);
  • 静态内部类;
  • 枚举单例;

以上三种是推荐使用的,其他方式因为存在或多或少的缺点,如线程安全、效率低下问题不太推荐。

设计模式 ( 一 ) 单例模式相关推荐

  1. socket可以写成单例嘛_精读《设计模式 - Singleton 单例模式》

    Singleton(单例模式) Singleton(单例模式)属于创建型模式,提供一种对象获取方式,保证在一定范围内是唯一的. 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 其实单例模 ...

  2. C#设计模式(1)——单例模式

    原文地址:http://www.cnblogs.com/zhili/p/SingletonPatterm.html 一.引言 最近在设计模式的一些内容,主要的参考书籍是<Head First 设 ...

  3. java设计模式之单例模式(七种方法)

    单例模式:个人认为这个是最简单的一种设计模式,而且也是在我们开发中最常用的一个设计模式. 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个 ...

  4. java单例模式的七种写法_Java设计模式之单例模式的七种写法

    什么是单例模式? 单例模式是一种常见的设计模式,单例模式的写法有很多种,这里主要介绍三种: 懒汉式单例模式.饿汉式单例模式.登记式单例 . 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类 ...

  5. go设计模式之单例模式

    在这里插入图片描述# go设计模式之单例模式 在软件开发时,经常会遇到有些对象需要保证只有一个实例的,那么这种设计模式就应用而生. 定义 单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模 ...

  6. 一篇博客读懂设计模式之---单例模式

    一篇博客读懂设计模式之---单例模式 一.  单例模式 单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处 ...

  7. Java 设计模式(3)单例模式

    前言 概念: java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自 ...

  8. socket可以写成单例嘛_精读设计模式 Singleton 单例模式

    Singleton(单例模式) Singleton(单例模式)属于创建型模式,提供一种对象获取方式,保证在一定范围内是唯一的. 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 其实单例模 ...

  9. 设计模式之单例模式——Singleton

                        设计模式之单例模式--Singleton 设计意图: 保证类仅有一个实例,并且可以供应用程序全局使用.为了保证这一点,就需要这个类自己创建自己的对象,并且对外有 ...

  10. 实践GoF的设计模式:单例模式

    本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:单例模式>,作者: 元闰子. 简述 GoF 对单例模式(Singleton)的定义如下: Ensure a class onl ...

最新文章

  1. 新的理念、 新的解决方案、 新的Azure Stack技术预览
  2. [图]为C# Windows服务添加安装程序
  3. 0046算法笔记——【随机化算法】舍伍德随机化思想解决跳跃表问题
  4. 状态栏消息提示——使用Notification
  5. 整合swagger2生成Restful Api接口文档
  6. c#Struts框架理念和自制Struts框架下 复杂版
  7. 字段中存在空值的问题测试
  8. Scala基础知识笔记2
  9. 二、CSS知识总结(上篇)
  10. 后端开发:数据持久化框架为什么放弃Hibernate、JPA、Mybatis,最终选择JDBCTemplate!...
  11. 人工智能 21 个子领域高被引学者Top 3
  12. 买断变订阅!苹果第一付费软件被骂上热搜 官方回应
  13. 在WPF里面显示DIB图片格式的图片
  14. paip.;论全文检索实现方式lucene Sphinx solr以及比较
  15. 生产环境下服务器台账
  16. 【学习笔记】在KEIL中stm32移植51代码时位定义变量的替换
  17. MD5信息摘要算法原理及破解原理
  18. 为什么有的计算机没有ppt,电脑上没有ppt怎么办
  19. Linux基础知识------账号和权限管理
  20. XMUOJ·纸片选择

热门文章

  1. java架构专题涨价_关于单量预测和动态定价的一些思考
  2. phonegap2.9.1 android 环境搭建,PhoneGap 开发环境搭建
  3. spring 配置项 随机_Spring Boot--从配置文件中获取随机数
  4. Anormaly_Detection_with_Keras
  5. 算法:动态规划 最大连续子数组和 Maximum Subarray
  6. 极客大学架构师训练营 听课总结 - 架构视图,设计文档 -- 第二课
  7. java求两个时间相差月_java计算两个时间相差几个月
  8. Wide Deep 模型详解
  9. android 扩展textview,Android可收缩/扩展的TextView【1】
  10. 【生信进阶练习1000days】day22-复习day1~day14的知识点