在所有的设计模式中,单例模式是我们在项目开发中最为常见的设计模式之一,而单例模式有很多种实现方式,你是否都了解呢?高并发下如何保证单例模式的线程安全性呢?如何保证序列化后的单例对象在反序列化后任然是单例的呢?这些问题在看了本文之后都会一一的告诉你答案,赶快来阅读吧!

什么是单例模式?

在文章开始之前我们还是有必要介绍一下什么是单例模式。单例模式是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种模式方法。

从概念中体现出了单例的一些特点:

(1)、在任何情况下,单例类永远只有一个实例存在

(2)、单例需要有能力为整个系统提供这一唯一实例

为了便于读者更好的理解这些概念,下面给出这么一段内容叙述:

在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

正是由于这个特点,单例对象通常作为程序中的存放配置信息的载体,因为它能保证其他对象读到一致的信息。例如在某个服务器程序中,该服务器的配置信息可能存放在数据库或文件中,这些配置数据由某个单例对象统一读取,服务进程中的其他对象如果要获取这些配置信息,只需访问该单例对象即可。这种方式极大地简化了在复杂环境 下,尤其是多线程环境下的配置管理,但是随着应用场景的不同,也可能带来一些同步问题。

各式各样的单例实现

温馨提示:本文叙述中涉及到的相关源码可以在这里进行下载源码,读者可免积分下载。

1、饿汉式单例

饿汉式单例是指在方法调用前,实例就已经创建好了。下面是实现代码:

  1.  
    package org.mlinge.s01;
  2.  
     
  3.  
    public class MySingleton {
  4.  
     
  5.  
    private static MySingleton instance = new MySingleton();
  6.  
     
  7.  
    private MySingleton(){}
  8.  
     
  9.  
    public static MySingleton getInstance() {
  10.  
    return instance;
  11.  
    }
  12.  
     
  13.  
    }

以上是单例的饿汉式实现,我们来看看饿汉式在多线程下的执行情况,给出一段多线程的执行代码:

  1.  
    package org.mlinge.s01;
  2.  
     
  3.  
    public class MyThread extends Thread{
  4.  
     
  5.  
    @Override
  6.  
    public void run() {
  7.  
    System.out.println(MySingleton.getInstance().hashCode());
  8.  
    }
  9.  
     
  10.  
    public static void main(String[] args) {
  11.  
     
  12.  
    MyThread[] mts = new MyThread[10];
  13.  
    for(int i = 0 ; i < mts.length ; i++){
  14.  
    mts[i] = new MyThread();
  15.  
    }
  16.  
     
  17.  
    for (int j = 0; j < mts.length; j++) {
  18.  
    mts[j].start();
  19.  
    }
  20.  
    }
  21.  
    }

以上代码运行结果:

1718900954
1718900954
1718900954
1718900954
1718900954
1718900954
1718900954
1718900954
1718900954
1718900954

从运行结果可以看出实例变量额hashCode值一致,这说明对象是同一个,饿汉式单例实现了。

2、懒汉式单例

懒汉式单例是指在方法调用获取实例时才创建实例,因为相对饿汉式显得“不急迫”,所以被叫做“懒汉模式”。下面是实现代码:

  1.  
    package org.mlinge.s02;
  2.  
     
  3.  
    public class MySingleton {
  4.  
     
  5.  
    private static MySingleton instance = null;
  6.  
     
  7.  
    private MySingleton(){}
  8.  
     
  9.  
    public static MySingleton getInstance() {
  10.  
    if(instance == null){//懒汉式
  11.  
    instance = new MySingleton();
  12.  
    }
  13.  
    return instance;
  14.  
    }
  15.  
    }

这里实现了懒汉式的单例,但是熟悉多线程并发编程的朋友应该可以看出,在多线程并发下这样的实现是无法保证实例实例唯一的,甚至可以说这样的失效是完全错误的,下面我们就来看一下多线程并发下的执行情况,这里为了看到效果,我们对上面的代码做一小点修改:

  1.  
    package org.mlinge.s02;
  2.  
     
  3.  
    public class MySingleton {
  4.  
     
  5.  
    private static MySingleton instance = null;
  6.  
     
  7.  
    private MySingleton(){}
  8.  
     
  9.  
    public static MySingleton getInstance() {
  10.  
    try {
  11.  
    if(instance != null){//懒汉式
  12.  
     
  13.  
    }else{
  14.  
    //创建实例之前可能会有一些准备性的耗时工作
  15.  
    Thread.sleep(300);
  16.  
    instance = new MySingleton();
  17.  
    }
  18.  
    } catch (InterruptedException e) {
  19.  
    e.printStackTrace();
  20.  
    }
  21.  
    return instance;
  22.  
    }
  23.  
    }

这里假设在创建实例前有一些准备性的耗时工作要处理,多线程调用:

  1.  
    package org.mlinge.s02;
  2.  
     
  3.  
    public class MyThread extends Thread{
  4.  
     
  5.  
    @Override
  6.  
    public void run() {
  7.  
    System.out.println(MySingleton.getInstance().hashCode());
  8.  
    }
  9.  
     
  10.  
    public static void main(String[] args) {
  11.  
     
  12.  
    MyThread[] mts = new MyThread[10];
  13.  
    for(int i = 0 ; i < mts.length ; i++){
  14.  
    mts[i] = new MyThread();
  15.  
    }
  16.  
     
  17.  
    for (int j = 0; j < mts.length; j++) {
  18.  
    mts[j].start();
  19.  
    }
  20.  
    }
  21.  
    }

执行结果如下:

1210420568
1210420568
1935123450
1718900954
1481297610
1863264879
369539795
1210420568
1210420568
602269801

从这里执行结果可以看出,单例的线程安全性并没有得到保证,那要怎么解决呢?

3、线程安全的懒汉式单例

要保证线程安全,我们就得需要使用同步锁机制,下面就来看看我们如何一步步的解决 存在线程安全问题的懒汉式单例(错误的单例)。

(1)、 方法中声明synchronized关键字

出现非线程安全问题,是由于多个线程可以同时进入getInstance()方法,那么只需要对该方法进行synchronized的锁同步即可:

  1.  
    package org.mlinge.s03;
  2.  
     
  3.  
    public class MySingleton {
  4.  
     
  5.  
    private static MySingleton instance = null;
  6.  
     
  7.  
    private MySingleton(){}
  8.  
     
  9.  
    public synchronized static MySingleton getInstance() {
  10.  
    try {
  11.  
    if(instance != null){//懒汉式
  12.  
     
  13.  
    }else{
  14.  
    //创建实例之前可能会有一些准备性的耗时工作
  15.  
    Thread.sleep(300);
  16.  
    instance = new MySingleton();
  17.  
    }
  18.  
    } catch (InterruptedException e) {
  19.  
    e.printStackTrace();
  20.  
    }
  21.  
    return instance;
  22.  
    }
  23.  
    }

此时任然使用前面验证多线程下执行情况的MyThread类来进行验证,将其放入到org.mlinge.s03包下运行,执行结果如下:

1689058373
1689058373
1689058373
1689058373
1689058373
1689058373
1689058373
1689058373
1689058373
1689058373

从执行结果上来看,问题已经解决了,但是这种实现方式的运行效率会很低。同步方法效率低,那我们考虑使用同步代码块来实现:

(2)、 同步代码块实现

  1.  
    package org.mlinge.s03;
  2.  
     
  3.  
    public class MySingleton {
  4.  
     
  5.  
    private static MySingleton instance = null;
  6.  
     
  7.  
    private MySingleton(){}
  8.  
     
  9.  
    //public synchronized static MySingleton getInstance() {
  10.  
    public static MySingleton getInstance() {
  11.  
    try {
  12.  
    synchronized (MySingleton.class) {
  13.  
    if(instance != null){//懒汉式
  14.  
     
  15.  
    }else{
  16.  
    //创建实例之前可能会有一些准备性的耗时工作
  17.  
    Thread.sleep(300);
  18.  
    instance = new MySingleton();
  19.  
    }
  20.  
    }
  21.  
    } catch (InterruptedException e) {
  22.  
    e.printStackTrace();
  23.  
    }
  24.  
    return instance;
  25.  
    }
  26.  
    }

这里的实现能够保证多线程并发下的线程安全性,但是这样的实现将全部的代码都被锁上了,同样的效率很低下。

(3)、 针对某些重要的代码来进行单独的同步(可能非线程安全)

针对某些重要的代码进行单独的同步,而不是全部进行同步,可以极大的提高执行效率,我们来看一下:

  1.  
    package org.mlinge.s04;
  2.  
     
  3.  
    public class MySingleton {
  4.  
     
  5.  
    private static MySingleton instance = null;
  6.  
     
  7.  
    private MySingleton(){}
  8.  
     
  9.  
    public static MySingleton getInstance() {
  10.  
    try {
  11.  
    if(instance != null){//懒汉式
  12.  
     
  13.  
    }else{
  14.  
    //创建实例之前可能会有一些准备性的耗时工作
  15.  
    Thread.sleep(300);
  16.  
    synchronized (MySingleton.class) {
  17.  
    instance = new MySingleton();
  18.  
    }
  19.  
    }
  20.  
    } catch (InterruptedException e) {
  21.  
    e.printStackTrace();
  22.  
    }
  23.  
    return instance;
  24.  
    }
  25.  
    }

此时同样使用前面验证多线程下执行情况的MyThread类来进行验证,将其放入到org.mlinge.s04包下运行,执行结果如下:

1481297610
397630378
1863264879
1210420568
1935123450
369539795
590202901
1718900954
1689058373
602269801

从运行结果来看,这样的方法进行代码块同步,代码的运行效率是能够得到提升,但是却没能保住线程的安全性。看来还得进一步考虑如何解决此问题。

(4)、 Double Check Locking 双检查锁机制(推荐)

为了达到线程安全,又能提高代码执行效率,我们这里可以采用DCL的双检查锁机制来完成,代码实现如下:

  1.  
    package org.mlinge.s05;
  2.  
     
  3.  
    public class MySingleton {
  4.  
     
  5.  
    //使用volatile关键字保其可见性
  6.  
    volatile private static MySingleton instance = null;
  7.  
     
  8.  
    private MySingleton(){}
  9.  
     
  10.  
    public static MySingleton getInstance() {
  11.  
    try {
  12.  
    if(instance != null){//懒汉式
  13.  
     
  14.  
    }else{
  15.  
    //创建实例之前可能会有一些准备性的耗时工作
  16.  
    Thread.sleep(300);
  17.  
    synchronized (MySingleton.class) {
  18.  
    if(instance == null){//二次检查
  19.  
    instance = new MySingleton();
  20.  
    }
  21.  
    }
  22.  
    }
  23.  
    } catch (InterruptedException e) {
  24.  
    e.printStackTrace();
  25.  
    }
  26.  
    return instance;
  27.  
    }
  28.  
    }

将前面验证多线程下执行情况的MyThread类放入到org.mlinge.s05包下运行,执行结果如下:

  1.  
    369539795
  2.  
    369539795
  3.  
    369539795
  4.  
    369539795
  5.  
    369539795
  6.  
    369539795
  7.  
    369539795
  8.  
    369539795
  9.  
    369539795
  10.  
    369539795

从运行结果来看,该中方法保证了多线程并发下的线程安全性。

这里在声明变量时使用了volatile关键字来保证其线程间的可见性;在同步代码块中使用二次检查,以保证其不被重复实例化。集合其二者,这种实现方式既保证了其高效性,也保证了其线程安全性。

4、使用静态内置类实现单例模式

DCL解决了多线程并发下的线程安全问题,其实使用其他方式也可以达到同样的效果,代码实现如下:

  1.  
    package org.mlinge.s06;
  2.  
     
  3.  
    public class MySingleton {
  4.  
     
  5.  
    //内部类
  6.  
    private static class MySingletonHandler{
  7.  
    private static MySingleton instance = new MySingleton();
  8.  
    }
  9.  
     
  10.  
    private MySingleton(){}
  11.  
     
  12.  
    public static MySingleton getInstance() {
  13.  
    return MySingletonHandler.instance;
  14.  
    }
  15.  
    }

以上代码就是使用静态内置类实现了单例模式,这里将前面验证多线程下执行情况的MyThread类放入到org.mlinge.s06包下运行,执行结果如下:

  1.  
    1718900954
  2.  
    1718900954
  3.  
    1718900954
  4.  
    1718900954
  5.  
    1718900954
  6.  
    1718900954
  7.  
    1718900954
  8.  
    1718900954
  9.  
    1718900954
  10.  
    1718900954

从运行结果来看,静态内部类实现的单例在多线程并发下单个实例得到了保证。

5、序列化与反序列化的单例模式实现

静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。

代码实现如下:

  1.  
    package org.mlinge.s07;
  2.  
     
  3.  
    import java.io.Serializable;
  4.  
     
  5.  
    public class MySingleton implements Serializable {
  6.  
     
  7.  
    private static final long serialVersionUID = 1L;
  8.  
     
  9.  
    //内部类
  10.  
    private static class MySingletonHandler{
  11.  
    private static MySingleton instance = new MySingleton();
  12.  
    }
  13.  
     
  14.  
    private MySingleton(){}
  15.  
     
  16.  
    public static MySingleton getInstance() {
  17.  
    return MySingletonHandler.instance;
  18.  
    }
  19.  
    }

序列化与反序列化测试代码:

  1.  
    package org.mlinge.s07;
  2.  
     
  3.  
    import java.io.File;
  4.  
    import java.io.FileInputStream;
  5.  
    import java.io.FileNotFoundException;
  6.  
    import java.io.FileOutputStream;
  7.  
    import java.io.IOException;
  8.  
    import java.io.ObjectInputStream;
  9.  
    import java.io.ObjectOutputStream;
  10.  
     
  11.  
    public class SaveAndReadForSingleton {
  12.  
     
  13.  
    public static void main(String[] args) {
  14.  
    MySingleton singleton = MySingleton.getInstance();
  15.  
     
  16.  
    File file = new File("MySingleton.txt");
  17.  
     
  18.  
    try {
  19.  
    FileOutputStream fos = new FileOutputStream(file);
  20.  
    ObjectOutputStream oos = new ObjectOutputStream(fos);
  21.  
    oos.writeObject(singleton);
  22.  
    fos.close();
  23.  
    oos.close();
  24.  
    System.out.println(singleton.hashCode());
  25.  
    } catch (FileNotFoundException e) {
  26.  
    e.printStackTrace();
  27.  
    } catch (IOException e) {
  28.  
    e.printStackTrace();
  29.  
    }
  30.  
     
  31.  
    try {
  32.  
    FileInputStream fis = new FileInputStream(file);
  33.  
    ObjectInputStream ois = new ObjectInputStream(fis);
  34.  
    MySingleton rSingleton = (MySingleton) ois.readObject();
  35.  
    fis.close();
  36.  
    ois.close();
  37.  
    System.out.println(rSingleton.hashCode());
  38.  
    } catch (FileNotFoundException e) {
  39.  
    e.printStackTrace();
  40.  
    } catch (IOException e) {
  41.  
    e.printStackTrace();
  42.  
    } catch (ClassNotFoundException e) {
  43.  
    e.printStackTrace();
  44.  
    }
  45.  
     
  46.  
    }
  47.  
    }

运行以上代码,得到的结果如下:

  1.  
    865113938
  2.  
    1442407170

从结果中我们发现,序列号对象的hashCode和反序列化后得到的对象的hashCode值不一样,说明反序列化后返回的对象是重新实例化的,单例被破坏了。那怎么来解决这一问题呢?

解决办法就是在反序列化的过程中使用readResolve()方法,单例实现的代码如下:

  1.  
    package org.mlinge.s07;
  2.  
     
  3.  
    import java.io.ObjectStreamException;
  4.  
    import java.io.Serializable;
  5.  
     
  6.  
    public class MySingleton implements Serializable {
  7.  
     
  8.  
    private static final long serialVersionUID = 1L;
  9.  
     
  10.  
    //内部类
  11.  
    private static class MySingletonHandler{
  12.  
    private static MySingleton instance = new MySingleton();
  13.  
    }
  14.  
     
  15.  
    private MySingleton(){}
  16.  
     
  17.  
    public static MySingleton getInstance() {
  18.  
    return MySingletonHandler.instance;
  19.  
    }
  20.  
     
  21.  
    //该方法在反序列化时会被调用,该方法不是接口定义的方法,有点儿约定俗成的感觉
  22.  
    protected Object readResolve() throws ObjectStreamException {
  23.  
    System.out.println("调用了readResolve方法!");
  24.  
    return MySingletonHandler.instance;
  25.  
    }
  26.  
    }
  27.  
     

再次运行上面的测试代码,得到的结果如下:

865113938
调用了readResolve方法!
865113938

从运行结果可知,添加readResolve方法后反序列化后得到的实例和序列化前的是同一个实例,单个实例得到了保证。

6、使用static代码块实现单例

静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性的实现单例设计模式。

  1.  
    package org.mlinge.s08;
  2.  
     
  3.  
    public class MySingleton{
  4.  
     
  5.  
    private static MySingleton instance = null;
  6.  
     
  7.  
    private MySingleton(){}
  8.  
     
  9.  
    static{
  10.  
    instance = new MySingleton();
  11.  
    }
  12.  
     
  13.  
    public static MySingleton getInstance() {
  14.  
    return instance;
  15.  
    }
  16.  
    }

测试代码如下:

  1.  
    package org.mlinge.s08;
  2.  
     
  3.  
    public class MyThread extends Thread{
  4.  
     
  5.  
    @Override
  6.  
    public void run() {
  7.  
    for (int i = 0; i < 5; i++) {
  8.  
    System.out.println(MySingleton.getInstance().hashCode());
  9.  
    }
  10.  
    }
  11.  
     
  12.  
    public static void main(String[] args) {
  13.  
     
  14.  
    MyThread[] mts = new MyThread[3];
  15.  
    for(int i = 0 ; i < mts.length ; i++){
  16.  
    mts[i] = new MyThread();
  17.  
    }
  18.  
     
  19.  
    for (int j = 0; j < mts.length; j++) {
  20.  
    mts[j].start();
  21.  
    }
  22.  
    }
  23.  
    }

运行结果如下:

  1.  
    1718900954
  2.  
    1718900954
  3.  
    1718900954
  4.  
    1718900954
  5.  
    1718900954
  6.  
    1718900954
  7.  
    1718900954
  8.  
    1718900954
  9.  
    1718900954
  10.  
    1718900954
  11.  
    1718900954
  12.  
    1718900954
  13.  
    1718900954
  14.  
    1718900954
  15.  
    1718900954

从运行结果看,单例的线程安全性得到了保证。

7、使用枚举数据类型实现单例模式

枚举enum和静态代码块的特性相似,在使用枚举时,构造方法会被自动调用,利用这一特性也可以实现单例:

  1.  
    package org.mlinge.s09;
  2.  
     
  3.  
    public enum EnumFactory{
  4.  
        
  5.  
        singletonFactory;
  6.  
        
  7.  
        private MySingleton instance;
  8.  
        
  9.  
        private EnumFactory(){//枚举类的构造方法在类加载是被实例化
  10.  
            instance = new MySingleton();
  11.  
        }
  12.  
            
  13.  
        public MySingleton getInstance(){
  14.  
            return instance;
  15.  
        }
  16.  
        
  17.  
    }
  18.  
     
  19.  
    class MySingleton{//需要获实现单例的类,比如数据库连接Connection
  20.  
        public MySingleton(){}
  21.  
    }

测试代码如下:

  1.  
    package org.mlinge.s09;
  2.  
     
  3.  
    public class MyThread extends Thread{
  4.  
     
  5.  
    @Override
  6.  
    public void run() {
  7.  
    System.out.println(EnumFactory.singletonFactory.getInstance().hashCode());
  8.  
    }
  9.  
     
  10.  
    public static void main(String[] args) {
  11.  
     
  12.  
    MyThread[] mts = new MyThread[10];
  13.  
    for(int i = 0 ; i < mts.length ; i++){
  14.  
    mts[i] = new MyThread();
  15.  
    }
  16.  
     
  17.  
    for (int j = 0; j < mts.length; j++) {
  18.  
    mts[j].start();
  19.  
    }
  20.  
    }
  21.  
    }

执行后得到的结果:

  1.  
    1481297610
  2.  
    1481297610
  3.  
    1481297610
  4.  
    1481297610
  5.  
    1481297610
  6.  
    1481297610
  7.  
    1481297610
  8.  
    1481297610
  9.  
    1481297610
  10.  
    1481297610

运行结果表明单例得到了保证,但是这样写枚举类被完全暴露了,据说违反了“职责单一原则”,那我们来看看怎么进行改造呢。

8、完善使用enum枚举实现单例模式

不暴露枚举类实现细节的封装代码如下:

  1.  
    package org.mlinge.s10;
  2.  
     
  3.  
    public class ClassFactory{
  4.  
     
  5.  
    private enum MyEnumSingleton{
  6.  
    singletonFactory;
  7.  
     
  8.  
    private MySingleton instance;
  9.  
     
  10.  
    private MyEnumSingleton(){//枚举类的构造方法在类加载是被实例化
  11.  
    instance = new MySingleton();
  12.  
    }
  13.  
     
  14.  
    public MySingleton getInstance(){
  15.  
    return instance;
  16.  
    }
  17.  
    }
  18.  
     
  19.  
    public static MySingleton getInstance(){
  20.  
    return MyEnumSingleton.singletonFactory.getInstance();
  21.  
    }
  22.  
    }
  23.  
     
  24.  
    class MySingleton{//需要获实现单例的类,比如数据库连接Connection
  25.  
    public MySingleton(){}
  26.  
    }
  27.  
     

验证单例实现的代码如下:

  1.  
    package org.mlinge.s10;
  2.  
     
  3.  
    public class MyThread extends Thread{
  4.  
     
  5.  
    @Override
  6.  
    public void run() {
  7.  
    System.out.println(ClassFactory.getInstance().hashCode());
  8.  
    }
  9.  
     
  10.  
    public static void main(String[] args) {
  11.  
     
  12.  
    MyThread[] mts = new MyThread[10];
  13.  
    for(int i = 0 ; i < mts.length ; i++){
  14.  
    mts[i] = new MyThread();
  15.  
    }
  16.  
     
  17.  
    for (int j = 0; j < mts.length; j++) {
  18.  
    mts[j].start();
  19.  
    }
  20.  
    }
  21.  
    }

验证结果:

  1.  
    1935123450
  2.  
    1935123450
  3.  
    1935123450
  4.  
    1935123450
  5.  
    1935123450
  6.  
    1935123450
  7.  
    1935123450
  8.  
    1935123450
  9.  
    1935123450
  10.  
    1935123450

验证结果表明,完善后的单例实现更为合理。

以上就是本文要介绍的所有单例模式的实现,相信认真阅读的读者都已经明白文章开头所引入的那几个问题了,祝大家读得开心:-D!

备注:本文的编写思路和实例源码参照《Java多线程编程核心技术》-(高洪岩)一书中第六章的学习案例撰写。

[No000016F]高并发下线程安全的单例模式(最全最经典)的更多相关文章

  1. Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)(转)

    转自:http://blog.csdn.net/wuyuxing24/article/details/48758927 一, 背景 先说下我要实现的功能,server端一直在linux平台下面跑,当客 ...

  2. 配置开发支持高并发TCP连接的Linux应用程序全攻略

    http://blog.chinaunix.net/uid-20733992-id-3447120.html http://blog.chinaunix.net/space.php?uid=16480 ...

  3. Tomact高并发&Servlet线程处理

    Servlet/JSP技术和ASP.PHP等相比,由于其多线程运行而具有很高的执行效率.由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的安全性问题.然而 ...

  4. Java并发:线程安全的单例模式

    转载请注明出处:jiq•钦'stechnical Blog 1.饿汉式 public class Singleton { private final static Singleton INSTANCE ...

  5. 【高并发】不得不说的线程池与ThreadPoolExecutor类浅析

    大家好,我是冰河~~ 今天,我们一起来简单聊聊线程池中的ThreadPoolExecutor类,好了,不多说了,开始进入今天的正题. 一.抛砖引玉 既然Java中支持以多线程的方式来执行相应的任务,但 ...

  6. java高并发核心要点|系列1|开篇

    在java高并发编程,有几个很重要的内容: 1.CAS算法 2.CPU重排序 3.缓存行伪共享 我们先来说说高并发世界中的主要关键问题是什么? 是数据共享. 因为多线程之间要共享数据,就会遇到各种问题 ...

  7. 多线程模式下高并发的环境中唯一确保单例模式---DLC双端锁

    DLC双端锁,CAS,ABA问题 一.什么是DLC双端锁?有什么用处? 为了解决在多线程模式下,高并发的环境中,唯一确保单例模式只能生成一个实例 多线程环境中,单例模式会因为指令重排和线程竞争的原因会 ...

  8. Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%。再往后,每提高0.1%,优化难度成指数级增长了。哪怕是千分之一,也直接影响用户体验,影响每天上万张机票的销售额。 在高并发场景下,提供了保证线程安全的对象、方法。比如经典的ConcurrentHashMap,它比起HashMap,有更小粒度的锁,并发读写性能更好。线程安全的StringBuilder取代S

    Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%.再往后,每提高0.1%,优化难度成指数级增长了.哪怕是千分之一,也直接影响用户体验,影响每天上万张机 ...

  9. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

随机推荐

  1. C#面试题(转载)

    原文地址:100道C#面试题(.net开发人员必备)  https://blog.csdn.net/u013519551/article/details/51220841 1. .NET和C#有什么区 ...

  2. 在Centos 6 64bit 上安装 Hyperic HQ 5.8.2.1 中文版

    原文:https://my.oschina.net/hyperichq/blog/306791 环境描述: [test@tester ~]$ cat /etc/issue CentOS release ...

  3. idea git 使用

    第一部  测试  本地git 是否已经成功安装 centos 7 发行版默认已经安装 第二部: 测试 github 连接是否成功,需要输入用户密码 第三部:创建git项目管理两种方式 1. 菜单 VC ...

  4. java中的数据加密4 数字签名

    数字签名 它是确定交换消息的通信方身份的第一个级别.A通过使用公钥加密数据后发给B,B利用私钥解密就得到了需要的数据,问题来了,由于都是使用公钥加密,那么如何检验是A发过来的消息呢?上面也提到了一点, ...

  5. MUI 打包android app

    自有证书生成方法 manifest配置 (2).图标配置:所有图片格式必须是png,且严格符合分辨率要求.使用其他图片格式重命名为png会导致打包失败.配置图标时选择自动生成所有适用图标,选择一个大图 ...

  6. Java知多少(62)线程同步

    当两个或两个以上的线程需要共享资源,它们需要某种方法来确定资源在某一刻仅被一个线程占用.达到此目的的过程叫做同步(synchronization).像你所看到的,Java为此提供了独特的,语言水平上的 ...

  7. 【转】xhEditor技术手册 网页编辑器基础教程

    1. xhEditor入门基础 1.1. 在线可视化HTML编辑器概述1.2. 获取xhEditor1.3. xhEditor运行环境1.4. xhEditor基本使用指南 1.1. 在线可视化HTM ...

  8. 第四百零一节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署virtualenv虚拟环境安装,与Python虚拟环境批量安装模块

    第四百零一节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署virtualenv虚拟环境安装,与Python虚拟环境批量安装模块 virtualenv简介 1.安装virtuale ...

  9. Python——特殊属性与方法

    Python 对象 中以双下划线开头和结尾的属性称为特殊属性,由于对象的方法也属于属性,因此以双下划线开头和结尾的方法称为特殊方法.对这些对象执行一些特定的运算时,Python会自动视图调用这些实例的 ...

  10. Solr学习笔记——查询

    1.进入Solr管理界面http://localhost:8983/solr/ 可以看到Query中有若干的参数,其意义如下(参考:http://www.jianshu.com/p/3c4cae5de ...