`
5452
  • 浏览: 28874 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

静态类和单例的抉择

阅读更多
先说说我要实现的要求:我要一个Map,这个Map是常量,但是它要进行初始化,填充数据。而且这个Map要可以重用,实现优雅点的
public class ApproveMap {

	private static Map<String, String> approveCodeMap = new HashMap<String, String>();

	/**
	 * @return
	 */
	public static Map<String, String> getApprove() {
		synchronized (approveCodeMap) {
			if (approveCodeMap.isEmpty())
				setApprove();
		}
		return approveCodeMap;
	}

	private static void setApprove() {
		/**
		 *
		 */
		approveCodeMap.put("101102", "11_0003_0001");
		approveCodeMap.put("101103", "11_0003_0004");
		approveCodeMap.put("101104", "11_0003_0005");
		approveCodeMap.put("101105", "11_0003_0002");
		approveCodeMap.put("101106", "11_0003_0003");
		approveCodeMap.put("101107", "11_0003_0006");

	}
}


以上是我写的一个方式,总觉得别扭,大家一块看看有什么更好的方法。

2010年6月更新:
这个东西看着确实不是东西,有静态初始化块了,没必要有getter了,实在是。。。
public class ApproveMap {

	public static final Map<String, String> approveCodeMap = new HashMap<String, String>();
	static {
		/**
		 *
		 */
		approveCodeMap.put("101102", "11_0003_0001");
		approveCodeMap.put("101103", "11_0003_0004");
		approveCodeMap.put("101104", "11_0003_0005");
		approveCodeMap.put("101105", "11_0003_0002");
		approveCodeMap.put("101106", "11_0003_0003");
		approveCodeMap.put("101107", "11_0003_0006");

	}
}
分享到:
评论
20 楼 andot 2009-02-24  
icewubin 写道
andot 写道
icewubin 写道
andot 写道
静态初始化也要加锁,在多线程模式下,你不能保证在初始化之前不会被访问。

Java中的static代码块,不需要加锁的。


它是自动加锁的吗?

因为Java的类加载的特性,static代码块只会运行一次,所以不需要锁。

一般简单来说,当程序第一次调用到这个类的某个变量或方法(除了static final的变量),都算是首次加载这个类到内存中准备调用,但是调用之前,先初始化static的变量,然后执行static代码段(暂且认为static代码段在static变量定义之后),此时才算类加载完毕,再运行之前的调用请求。

当然后续再有其他调用请求,这个类加载的过程不会再执行一遍的。


如果是你说的这样的话,如果不加锁还是有可能会出问题的。

比如当第一次访问这个类的静态方法来获取HashMap中的值时,他会先执行static块,在执行static块的时候(没完成),如果另一个线程也同时调用这个类的静态方法来获取HashMap中的值时,就会有冲突了(比如还没有初始化完,得不到希望的值)。所以,就算在static块中初始化HashMap的元素,也还是加锁比较好。
19 楼 icewubin 2009-02-24  
chan.d 写道
前阵子碰到类似的问题,

这样处理的,

static{

    map = makeUnreachUrl(version);

}

    public static Map makeUnreachUrl(int version){
           .....
           return map;
}

因为初始化的时候需要根据version的值判断要加入map的对象,
所以是以上写法。

再说,在static块中直接写感觉有点不优雅的感觉。

Java本身就没动态语言优雅,将就吧,不然当你看到很多匿名内部类,更会感到恶心。
18 楼 icewubin 2009-02-24  
andot 写道
icewubin 写道
andot 写道
静态初始化也要加锁,在多线程模式下,你不能保证在初始化之前不会被访问。

Java中的static代码块,不需要加锁的。


它是自动加锁的吗?

因为Java的类加载的特性,static代码块只会运行一次,所以不需要锁。

一般简单来说,当程序第一次调用到这个类的某个变量或方法(除了static final的变量),都算是首次加载这个类到内存中准备调用,但是调用之前,先初始化static的变量,然后执行static代码段(暂且认为static代码段在static变量定义之后),此时才算类加载完毕,再运行之前的调用请求。

当然后续再有其他调用请求,这个类加载的过程不会再执行一遍的。
17 楼 chan.d 2009-02-24  
前阵子碰到类似的问题,

这样处理的,

static{

    map = makeUnreachUrl(version);

}

    public static Map makeUnreachUrl(int version){
           .....
           return map;
}

因为初始化的时候需要根据version的值判断要加入map的对象,
所以是以上写法。

再说,在static块中直接写感觉有点不优雅的感觉。
16 楼 andot 2009-02-24  
icewubin 写道
andot 写道
静态初始化也要加锁,在多线程模式下,你不能保证在初始化之前不会被访问。

Java中的static代码块,不需要加锁的。


它是自动加锁的吗?
15 楼 icewubin 2009-02-24  
andot 写道
静态初始化也要加锁,在多线程模式下,你不能保证在初始化之前不会被访问。

Java中的static代码块,不需要加锁的。
14 楼 whaosoft 2009-02-23  
没明白你要干嘛!!!!!!
13 楼 bachmozart 2009-02-23  
这个好像不需要抉择,static 块就完了,同步开销没必要时能省就省,我见过并发量大到一定程度时,竞争一个锁居然要花1秒
12 楼 yighter 2009-02-23  
类变量存在方法区,对象存在堆中,倾向于使用单例。
11 楼 case0079 2009-02-23  
这种需求下静态和单例有矛盾吗?
单例不过是不可以 NEW一个对象
10 楼 unsid 2009-02-23  
一个启动慢,一个第一次登陆慢
9 楼 yyjn12 2009-02-23  

# synchronized (approveCodeMap) { 
#             if (approveCodeMap.isEmpty()) 
#                 setApprove(); 
#         } 
的外边,再加一层  if(approveCodeMap.isEmpty())

双重检查锁,效率会比这个高很多。
这个不成了,每次取这个map都要排队了吗
8 楼 cdredfox 2009-02-23  
类似这样的需求,一至使用静态块
7 楼 forgood 2009-02-23  
同意楼上的观点,使用静态代码块,比较简洁,直接。
6 楼 5452 2009-02-20  
嗯,看了看,想了想,还是觉得大家说的静态代码块比较简洁,直接,我喜欢,谢谢
5 楼 taupo 2009-02-19  
andot 写道
静态初始化也要加锁,在多线程模式下,你不能保证在初始化之前不会被访问。

静态初始化需要枷锁吗?
静态变量是虚拟机加载类 的时候初始化的,如果第一次访问某个类的时候,该类没有被加载,虚拟机就会去加载该类
同时初始化静态变量

这和线程没有关系吧?
4 楼 andot 2009-02-19  
静态初始化也要加锁,在多线程模式下,你不能保证在初始化之前不会被访问。
3 楼 riching 2009-02-19  
dennis_zane 写道
直接初始化不就完了,非要搞个加锁

嗯,看网上说的单利模式的实现倾向于直接实现这种方式
2 楼 dennis_zane 2009-02-19  
直接初始化不就完了,非要搞个加锁
1 楼 dennis_zane 2009-02-19  
直接静态初始化不就完了,非要搞个加锁
  static{
     map.put....
  }

相关推荐

    QT静态单例管理信号和槽

    QT静态单例管理信号和槽是Qt框架中一种常见的设计模式,用于确保应用程序中只有一个特定类的实例。在Qt编程中,单例模式通常用于管理全局资源,如数据库连接、配置文件读取或系统设置。这里我们将深入探讨如何在Qt中...

    Java静态内部类实现单例过程

    在Java中,有多种实现单例的方式,包括饿汉式、懒汉式、双重检查锁定(DCL)、静态内部类和枚举。这里我们将重点讨论静态内部类和枚举实现单例的过程。 首先,让我们来看看静态内部类实现单例的方式: ```java ...

    单例模式中声明静态自己类型的指针编译显示未定义处理

    单例模式是软件设计模式中的一种,用于控制类的实例化过程,确保一个类只有一个实例,并提供一个全局访问点。这种模式在系统中需要频繁创建和销毁的对象,或者需要共享资源的情况下非常有用。然而,实现单例模式时,...

    Java单例模式实现静态内部类方法示例

    在Java中,单例模式可以通过多种方式实现,包括懒汉式、饿汉式、双重检查锁定和静态内部类方法等。今天,我们主要介绍了Java单例模式实现静态内部类方法示例,涉及构造函数私有化等相关内容。 单例模式的定义 单例...

    Java 单例模式 工具类

    通过`SingletonFactory`工具类,我们不仅可以方便地使用各种单例模式,还可以对自定义的单例进行统一管理和访问,提高了代码的可维护性和灵活性。在实际开发中,应根据项目需求选择适合的单例实现方式,以保证代码的...

    joomla里面的单例模式和纯静态类

    在Joomla!涉及到了很多的单例模式,比如JFactory,JURI等等。 对于一个请求中需要一个对象实例的,joomla大多采用了单例模式,可以避免重复实例化带来的资源浪费和性能损耗。

    php单例模式实例

    单例模式的核心思想是限制类的实例化过程,确保在程序运行期间,类的实例只有一个。通过控制类的构造函数,使其不能被外部直接实例化,而是通过一个静态方法来获取唯一的实例。这样,无论何时何地,只要调用这个静态...

    Java中的静态变量静态方法静态块与静态类.docx

    Java 中的静态变量、静态方法、静态块和静态类 Java 中的静态变量、静态方法、静态块和静态类是 Java 编程语言的四个重要概念,它们之间存在着紧密的关系。下面将对这四个概念进行详细的介绍。 一、静态变量...

    设计模式之单例模式(结合工厂模式)

    此外,单例模式还有几种变体,比如静态内部类单例和枚举单例。静态内部类单例利用Java类加载机制保证了线程安全,而枚举单例则是Java中实现单例的最佳方式,因为它天然支持序列化且防止反射攻击。 在代码实现上,...

    java中的单例模式

    静态内部类单例利用JVM保证了类加载的线程安全性,而枚举单例则是一种既简洁又线程安全的实现方式,也是官方推荐的单例实现方式。 ```java public enum Singleton { INSTANCE; // ... } ``` 在使用单例模式时,...

    Java中的单例模式与静态类

    单例模式与静态类(一个类,所有方法为静态方法)是另一个非常有趣的问题,在《Java中有关单例模式的面试问题》博文中露掉了,由于单例模式和静态类都具有良好的访问性,它们之间有许多相似之处,例如,两者可以直接...

    java使用静态关键字实现单例模式

    在上面的代码中,我们定义了一个 SingletonMode 类,它有一个私有的构造方法和一个公有的静态方法 getInstance()。getInstance() 方法用于获取 SingletonMode 的实例,如果实例不存在,则创建一个新的实例。 测试...

    java单例设计模式 4中实现方式,重点介绍了静态内部类的实现方式

    静态内部类单例模式利用了Java语言中静态内部类的特性来实现单例模式。具体来说它将单例对象的创建延迟到静态内部类被加载时才执行,从而避免了多线程环境下的同步问题。下面是一个简单的示例代码: ```java public...

    java 设计模式 单例模式

    //单例模式,始终只产生一个对象 /*public class SingleTest { public static void main(String[] args) { SingleTon singleTon1=SingleTon.getInstance(); SingleTon singleTon2=SingleTon.getInstance(); ...

    这可能是最全的单例模式了

    静态内部类实现单例模式5. 饿汉实现单例模式6. 饿汉变种实现单例模式7. 枚举实现单例模式static修饰下是怎么做到线程安全的?完全不使用synchronized实现单例模式1. CAS(AtomicReference)实现单例模式2. ...

    singleton_crash:演示由多个动态库链接的静态库中的单例导致的崩溃

    然而,如果不正确地处理单例,特别是在涉及动态库和静态库的情况下,可能会导致各种问题,甚至引发程序崩溃。标题和描述所提到的"singleton_crash"就是这种情况的一个实例,它探讨了当静态库被多个动态库链接时,...

    静态内部类

    根据内部类是否声明为static,它们被分为非静态内部类(也称为成员内部类)和静态内部类。 #### 二、静态内部类的特点 静态内部类具有以下特点: 1. **独立性**:静态内部类与外部类之间没有依赖关系,即使外部类...

    c++单例模式线程日志类

    在这个特定的场景中,我们讨论的是一个实现了单例模式的日志类,该类专为多线程环境设计,具备日志等级控制、精确的时间戳以及可变长参数和标准格式化输出的功能。 首先,让我们深入了解单例模式。单例模式的主要...

    Oracle jdbc 单例 工具类

    - 静态内部类单例:利用类加载机制保证线程安全,避免了同步开销。 4. **工具类设计**: - `DB.java`:可能包含静态方法,如`getConnection()`,返回数据库连接。使用单例模式确保全局只存在一个`Connection`实例...

Global site tag (gtag.js) - Google Analytics