Java高并发之设计模式

Java高并发之设计模式

 

单例

单例是最常见的一种设计模式, 一般用于全局对象管理, 比如xml配置读写之类的.

一般分为懒汉式, 饿汉式.

懒汉式: 方法上加synchronized

public static synchronized Singleton getInstance() { 
        if (single == null) {   
            single = new Singleton(); 
        }   
        return single; 
}

这种方式, 由于每次获取示例都要获取锁, 不推荐使用, 性能较差

懒汉式: 使用双检锁 + volatile

private volatile Singleton singleton = null;
    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

本方式是对直接在方法上加锁的一个优化, 好处在于只有第一次初始化获取了锁.

后续调用getInstance已经是无锁状态. 只是写法上稍微繁琐点.

至于为什么要volatile关键字, 主要涉及到jdk指令重排, 详见之前的博文: Java内存模型与指令重排

懒汉式: 使用静态内部类

public class Singleton {   
    private static class LazyHolder {   
      private static final Singleton INSTANCE = new Singleton();   
    }   
    private Singleton (){}   
    public static final Singleton getInstance() {   
      return LazyHolder.INSTANCE;   
    }   
}

该方式既解决了同步问题, 也解决了写法繁琐问题. 推荐使用改写法.

缺点在于无法响应事件来重新初始化INSTANCE.

饿汉式

public class Singleton1 { 
    private Singleton1() {} 
    private static final Singleton1 single = new Singleton1(); 
    public static Singleton1 getInstance() { 
        return single; 
    } 
}

缺点在于对象在一开始就直接初始化了.

Future模式

该模式的核心思想是异步调用. 有点类似于异步的ajax请求.

当调用某个方法时, 可能该方法耗时较久, 而在主函数中也不急于立刻获取结果.

因此可以让调用者立刻返回一个凭证, 该方法放到另外线程执行,

后续主函数拿凭证再去获取方法的执行结果即可, 其结构图如下

Java高并发之设计模式

jdk中内置了Future模式的支持, 其接口如下:

Java高并发之设计模式

通过FutureTask实现

注意其中两个耗时操作.

如果doOtherThing耗时2s, 则整个函数耗时2s左右.

如果doOtherThing耗时0.2s, 则整个函数耗时取决于RealData.costTime, 即1s左右结束.

public class FutureDemo1 {

public static void main(String[] args) throws InterruptedException, ExecutionException {
        FutureTask<String> future = new FutureTask<String>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return new RealData().costTime();
            }
        });
        ExecutorService service = Executors.newCachedThreadPool();
        service.submit(future);

System.out.println("RealData方法调用完毕");
        // 模拟主函数中其他耗时操作
        doOtherThing();
        // 获取RealData方法的结果
        System.out.println(future.get());
    }

private static void doOtherThing() throws InterruptedException {
        Thread.sleep(2000L);
    }
}

class RealData {

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/083e568311e9022afc3de0ec21a754aa.html