java单例模式代码
来源:互联网 发布:2017年淘宝开店流程 编辑:程序博客网 时间:2024/05/13 20:32
单例模式,在程序运行期间只有一个实例存在。
简单饿汉式单例模式实现代码如下:
package com.demo;public class Singleton {private Singleton() {}public static Singleton instance = new Singleton();public static Singleton getInstance() {return instance;}}
空间换时间。
简单懒汉式单例模式代码:
package com.demo;public class Singleton {private Singleton() {}public static Singleton instance;public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}
时间换空间。
简单的单例模式在多线程中容易出现问题,获取到的instance并非同一个对象。
同步方法实现单例模式:
package com.demo;public class Singleton {private Singleton() {}public static Singleton instance;public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}同步方法实现单例模式,效率低下,每一线程进入,都将阻塞其它线程的访问。
双重检查加锁实现单例模式:
package com.demo;public class Singleton {private Singleton() {}public static Singleton instance;public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if(instance == null){instance = new Singleton();}}}return instance;}}双重检查加锁(Double Checked Locking)很巧妙实现了单例模式,步骤为:
1、检查变量是否初始化(不加锁),如果已经初始化,立即返回变量。
2、获得锁。
3、再次检查变量是否初始化,如果变量已经被之前的某个线程初始化,立即返回此变量。
4、否则的话初始化变量并返回。
遗憾的是,传统的双重检查在java中并不可靠,双重检查锁定的理论是完美的,不幸的是,现实完全不同,java并不能保证它在单处理器或者多处理器计算机上顺利运行。
java平台的内存模型允许“无序写入”,instance的赋值和初始化的顺序是不确定的,在new 一个对象之前instance的值就已经不为null了,所以如果此时有线程执行到if(instance==null)的条件判断的时候就已经返回了一个不为null却未被初始化的instance。
解决方案:1、可以采用“饿汉式”解决,多线程下jvm可以保证类中静态内容只被初始化一次。
2、非要用双重加锁的话,变量前加volatile关键字(jdk5+),告知java虚拟机对加volatile的变量的读写不做优化排序。
package com.demo;public class Singleton {private Singleton() {}public static volatile Singleton instance;public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if(instance == null){instance = new Singleton();}}}return instance;}}
使用互斥锁,实现双重检查加锁单例模式:
package com.demo;import java.util.concurrent.locks.ReentrantLock;public class Singleton {/** * 私有构造 */private Singleton() {}/** * 互斥锁 */private static final ReentrantLock lock = new ReentrantLock();public static volatile Singleton instance;public static Singleton getInstance() {if (instance == null) {/** * 锁定访问线程,instance需要被修饰成volatile */lock.lock();try {if (instance == null) {instance = new Singleton();}} finally {/** * 解锁 */lock.unlock();}}return instance;}}
高级一点的采用读写锁方式:
package com.demo;import java.util.HashMap;import java.util.Map;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantReadWriteLock;/** * 单例模式注册类,此类本身使用饿汉式单例模式,用来管理所有的单例对象 * * @author kk * */public class SingletonRegister {/** * 私有构造 */private SingletonRegister() {}/** * 本身单例的引用 */private static final SingletonRegister instance = new SingletonRegister();/** * 维护注册信息的map */private static Map<String, Object> map = new HashMap<String, Object>();/** * 多线程的可重入的读写锁 */private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();/** * 可读锁,可以多个只读锁并存,锁定时可写锁不可用 */private static final Lock rLock = rwLock.readLock();/** * 可写锁,只能有一个,锁定时其它锁不可用 */private static final Lock wLock = rwLock.writeLock();public static Object getInstance(String className)throws InstantiationException, IllegalAccessException,ClassNotFoundException {Object instance = null;// 锁定读取锁rLock.lock();instance = map.get(className);try {if (instance != null) {return instance;}} finally {// 释放读取锁rLock.unlock();}// 锁定写入的锁wLock.lock();try {instance = map.get(className);if (instance != null) {return instance;}// 使用反射方式实例化单例对象instance = Class.forName(className).newInstance();// 放入map中存储map.put(className, instance);} finally {wLock.unlock();}return instance;}}
利用虚拟机特性,内部类方式实现单例模式:
package com.demo;public class Singleton {/** * 私有构造 */private Singleton() {}public static Singleton getInstance() {return SingletonHolder.instance;}/** * 内部类 * @author kk * */public static class SingletonHolder {private static final Singleton instance = new Singleton();}}内部类在使用到的时候,才开始加载初始化,由java虚拟机保证了线程安全以及延时加载。
总结:多线程总使用单例模式的建议是不要使用任何双重检查模式,优先考虑饿汉式以及内部类的方式实现单例模式即可,越简单越好;
0 0
- java单例模式代码
- 单例模式java代码
- Java 经典单例模式代码
- 单例模式(Java代码实现)
- java单例模式的代码例子
- java单例模式的示例代码
- 单例模式代码
- 单例模式 代码
- Java单例模式与工厂模式简单示例代码
- Java 单例模式及其几种实现代码
- java笔记-----代码块、单例设计模式、继承
- JAVA读取properties文件代码 单例模式
- JAVA学习代码——单例模式
- Java 单例设计模式 与 代码优化 学习笔记
- Java中的代码块、单例模式、修饰符
- Java单例代码
- java单例模式
- Java单例模式
- quartz—向job动态传递参数
- tar命令
- java队列
- [LeetCode]Maximum Subarray
- 真正的十年磨一剑 一个不屈不挠的老人75岁到85岁所经历的这些
- java单例模式代码
- ubuntu上修改mysql默认字符编码出现的Job failed to start解决方法
- java mkdir()和mkdirs()区别
- 各种内部排序的总结
- maven代理设置
- Effective C++ 29-33
- 书单:产品经理书籍资料全推荐
- android:layout_gravity 和 android:gravity 的区别
- 百度地图自定义Markers