- 浏览: 3046578 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
看老赵几天前提到double-check,昨天又提到属性的lazy加载,想起记这么一点:
在实现单例的时候,你是否真的需要用double-check之类的技巧来实现lazy创建实例?
使用单例模式但又想让它lazy创建实例,理由通常是“实例的创建可能伴随一些复杂的初始化计算,或者需要持有一些外部资源之类;如果程序中并没有使用到那个实例,那么付出的代码就白费了”。
但很多时候上述理由是个伪命题:不使用的类根本就不会被初始化。既然没有初始化,就不会付出代价去创建单例的实例。
Effective Java, 2nd推荐在Java 5或更新的版本中使用enum来实现Singleton模式。那看看这段代码的输出:
结果是:
虽然定义了Singleton类型,但程序中并没有使用它,所以也就没有引发它的初始化。
那么在main()里添加一行:
结果变为:
哪儿用哪儿才初始化。
只要实现Singleton的时候,该类上没有别的对外公开的静态变量或者静态方法,外界想要使用Singleton实例只能通过INSTANCE的话,那引发Singleton初始化的只有对INSTANCE的访问(这时初始化是正确的)或者通过反射(例如Class.forName(),这是例外情况)。
要是有信心代码里不会出现“例外情况”的话,又何必费神去实现double-check呢?
C#里则有些细微差异。某个类的静态初始化“想当然”也应该是初次使用的时候才进行,但实际上这取决于静态初始化逻辑是怎么写的。如果写成:
虽然代码中有Foo()使用了Singleton,但实际执行路径上没有经过Foo(),其它地方也没用过Singleton类,于是输出结果是:
但要是在Main()里添加一行:
输出结果跟想像的可能就不一样了:
这是因为C#中直接在静态变量声明的地方就初始化,而且没有显式提供静态构造器实现的话,会使类带上beforefieldinit标记,使得类的静态初始化提早执行。稍微改改,给Singleton类添加一个空的静态构造器的话……
会发现执行结果变为:
这种写法就不会使类带上beforefieldinit,于是初始化时间就跟“想像中”的一样,哪儿用到哪儿才初始化。把Instance的初始化整个挪到静态构造器里的结果也一样。
有时候费了力气去写个double-check搞不好还写错了,要是回头发现其实不用自己费神写lazy逻辑也能达到效果的话,那肯定郁闷坏了。引用老赵的帖的标题:如果是能简单解决的问题,就不用想得太复杂了
^ ^
嗯我知道这个办法。C#里应该也可以用吧,原理差不多。不过我没测试过,回头试试。
Guice 这边还有一种 singleton . 不过不知道在c#上是不是也适用..
在实现单例的时候,你是否真的需要用double-check之类的技巧来实现lazy创建实例?
使用单例模式但又想让它lazy创建实例,理由通常是“实例的创建可能伴随一些复杂的初始化计算,或者需要持有一些外部资源之类;如果程序中并没有使用到那个实例,那么付出的代码就白费了”。
但很多时候上述理由是个伪命题:不使用的类根本就不会被初始化。既然没有初始化,就不会付出代价去创建单例的实例。
Effective Java, 2nd推荐在Java 5或更新的版本中使用enum来实现Singleton模式。那看看这段代码的输出:
public class Program { public static void main(String[] args) { System.out.println("main()"); System.out.println("leaving main()"); } } enum Singleton { INSTANCE; Singleton() { System.out.println("Singleton()"); } }
结果是:
引用
main()
leaving main()
leaving main()
虽然定义了Singleton类型,但程序中并没有使用它,所以也就没有引发它的初始化。
那么在main()里添加一行:
public class Program { public static void main(String[] args) { System.out.println("main()"); Singleton s = Singleton.INSTANCE; System.out.println("leaving main()"); } } enum Singleton { INSTANCE; Singleton() { System.out.println("Singleton()"); } }
结果变为:
引用
main()
Singleton()
leaving main()
Singleton()
leaving main()
哪儿用哪儿才初始化。
只要实现Singleton的时候,该类上没有别的对外公开的静态变量或者静态方法,外界想要使用Singleton实例只能通过INSTANCE的话,那引发Singleton初始化的只有对INSTANCE的访问(这时初始化是正确的)或者通过反射(例如Class.forName(),这是例外情况)。
要是有信心代码里不会出现“例外情况”的话,又何必费神去实现double-check呢?
C#里则有些细微差异。某个类的静态初始化“想当然”也应该是初次使用的时候才进行,但实际上这取决于静态初始化逻辑是怎么写的。如果写成:
using System; public class Singleton { public static Singleton Instance = new Singleton(); private Singleton() { Console.WriteLine("Singleton()"); } } static class Program { static void Main(string[] args) { Console.WriteLine("Main()"); Console.WriteLine("leaving Main()"); } static void Foo() { var s = Singleton.Instance; } }
虽然代码中有Foo()使用了Singleton,但实际执行路径上没有经过Foo(),其它地方也没用过Singleton类,于是输出结果是:
引用
Main()
leaving Main()
leaving Main()
但要是在Main()里添加一行:
using System; public class Singleton { public static Singleton Instance = new Singleton(); private Singleton() { Console.WriteLine("Singleton()"); } } static class Program { static void Main(string[] args) { Console.WriteLine("Main()"); var s = Singleton.Instance; Console.WriteLine("leaving Main()"); } static void Foo() { var s = Singleton.Instance; } }
输出结果跟想像的可能就不一样了:
引用
Singleton()
Main()
leaving Main()
Main()
leaving Main()
这是因为C#中直接在静态变量声明的地方就初始化,而且没有显式提供静态构造器实现的话,会使类带上beforefieldinit标记,使得类的静态初始化提早执行。稍微改改,给Singleton类添加一个空的静态构造器的话……
using System; public class Singleton { public static Singleton Instance = new Singleton(); static Singleton() { } private Singleton() { Console.WriteLine("Singleton()"); } } static class Program { static void Main(string[] args) { Console.WriteLine("Main()"); var s = Singleton.Instance; Console.WriteLine("leaving Main()"); } static void Foo() { var s = Singleton.Instance; } }
会发现执行结果变为:
引用
Main()
Singleton()
leaving Main()
Singleton()
leaving Main()
这种写法就不会使类带上beforefieldinit,于是初始化时间就跟“想像中”的一样,哪儿用到哪儿才初始化。把Instance的初始化整个挪到静态构造器里的结果也一样。
有时候费了力气去写个double-check搞不好还写错了,要是回头发现其实不用自己费神写lazy逻辑也能达到效果的话,那肯定郁闷坏了。引用老赵的帖的标题:如果是能简单解决的问题,就不用想得太复杂了
^ ^
评论
4 楼
mercyblitz
2010-06-23
这是ClassLoader机制加载的,记载类的时候就synchronized啦,因此不会出现重复加载或者不可见的情况。
3 楼
RednaxelaFX
2009-09-06
Saito 写道
嗯我知道这个办法。C#里应该也可以用吧,原理差不多。不过我没测试过,回头试试。
2 楼
Saito
2009-09-06
睡糊涂了.. url 点成 quote 了..
1 楼
Saito
2009-09-06
引用
http://crazybob.org/2007/01/lazy-loading-singletons.html
Guice 这边还有一种 singleton . 不过不知道在c#上是不是也适用..
发表评论
-
Sun JDK1.4.2_28有TieredCompilation
2014-05-12 08:48 0原来以前Sun的JDK 1.4.2 update 28就已经有 ... -
IBM JVM notes (2014 ver)
2014-05-11 07:16 0Sovereign JIT http://publib.bou ... -
Java 8的lambda表达式在OpenJDK8中的实现
2014-02-04 12:08 0三月份JDK8就要发布首发了,现在JDK8 release c ... -
基于LLVM实现VM的JIT的一些痛点
2014-01-07 17:25 0同事Philip Reames Sanjoy Das http ... -
tailcall notes
2013-12-27 07:42 0http://blogs.msdn.com/b/clrcode ... -
《自制编程语言》的一些笔记
2013-11-24 00:20 0http://kmaebashi.com/programmer ... -
字符串的一般封装方式的内存布局 (1): 元数据与字符串内容,整体还是分离?
2013-11-07 17:44 22385(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局 (0): 拿在手上的是什么
2013-11-04 18:22 21486(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局
2013-11-01 12:55 0(Disclaimer:未经许可请 ... -
关于string,内存布局,C++ std::string,CoW
2013-10-30 20:45 0(Disclaimer:未经许可请 ... -
Function.prototype.bind
2013-09-24 18:07 0polyfill http://stackoverflow. ... -
Java的instanceof是如何实现的
2013-09-22 16:57 0Java语言规范,Java SE 7版 http://docs ... -
struct做参数不能从寄存器传?
2013-08-28 23:33 0test test test struct Foo { i ... -
也谈类型: 数据, 类型, 标签
2013-08-18 01:59 0numeric tower http://en.wikiped ... -
SDCC 2012上做的JVM分享
2012-10-17 16:35 32643刚把在SDCC 2012做的JVM分享的演示稿上传了。 演示 ... -
运行时支持系统的“重量”
2012-10-12 16:08 0运行时支持系统的“重量” 好久没写博客了,可写的话题已经堆积 ... -
class?metaclass?meta-what?
2011-04-05 19:43 0http://en.wikipedia.org/wiki/Me ... -
“代码模式”与抽象
2010-10-28 15:21 0嗯,我是说“代码模式”,不是“设计模式”;这里指的是在给定的场 ... -
lvalue与rvalue
2010-09-03 00:40 0http://en.wikipedia.org/wiki/Va ... -
动态链接的“依据”
2010-02-09 09:54 0动态链接,意味着在生成的“东西”里留有符号信息,等到运行时再r ...
相关推荐
使用此宏,可能具有static ,这些static要求在运行时执行代码才能进行初始化。 这包括需要堆分配的任何内容,例如向量或哈希图,以及需要计算非const函数调用的所有内容。最小支持的rustc 1.27.2+ 此版本已在CI中...
lazy-static.rs, 在 Rust 中,用于定义惰性计算的static 变量的小宏 lazy-static.rs在 Rust 中声明延迟求值的静态的宏。使用这里宏,可以以使 static s 在运行时要求执行代码,以便初始化。 这包括需要堆分配,如...
3. **初始化**:最后,JVM执行类的初始化,包括激活类的静态变量初始化和静态代码块。此时,类的静态成员会被真正地初始化为它们的指定值。 单态设计模式(Singleton Pattern)是一种常见的软件设计模式,它的目标...
例如,通过延迟初始化(Lazy Initialization),可以在需要时才创建对象,减少启动时的资源消耗。而及时清理则能避免资源浪费,提高系统的响应速度。 博文链接提到的iteye博客,可能提供了具体的代码示例和实践经验...
如果在头文件中只声明了静态成员变量,而没有在cpp文件中进行初始化,编译器会认为这是一个外部定义,需要在链接阶段找到对应的定义。如果找不到,就会出现“未定义的引用”错误。 针对这个错误,我们可以采取以下...
例如,在调用类的构造函数时,Java 会把变量初始化成确定的值。 5. 使用大写的 SQL 语句 在 JAVA + ORACLE 的应用系统开发中,java 中内嵌的 SQL 语句尽量使用大写的形式,以减轻 ORACLE 解析器的解析负担。 6. ...
2-创建一个静态私有变量数据类型是当前类的数据类型且不进行初始化 3-提供一个公有静态的获取当前对象的方法 4-进行判断, 若当前对象没有被创建, 创建对象, 否则返回 object LazyDemo extends App { def init():...
Java 中的变量初始化需要花费时间和空间,避免重复初始化变量可以提高性能。 5. 在 JAVA + ORACLE 的应用系统开发中,java 中内嵌的 SQL 语句尽量使用大写的形式,以减轻 ORACLE 解析器的解析负担。 使用大写的 ...
这意味着你可以为每个`Lazy<T>`实例指定一个初始化闭包,这个闭包将在首次访问时运行。 在实际使用中,Once_cell库常用于以下场景: 1. 全局配置:当需要在程序运行期间只初始化一次的全局配置时,可以利用Once_...
基本思想是在初始化单例对象时,进行两次检查:第一次在不加锁的情况下判断实例是否已经创建,若未创建,则进入同步代码块进行第二次检查。这样可以避免不必要的同步开销,提高程序效率。然而,原始的DCL在Java早期...
2. 懒汉式(Lazy Singleton):首次调用时初始化,延迟加载,但需要考虑线程同步问题。 ```csharp public sealed class Singleton { private static readonly Lazy<Singleton> lazy = new Lazy(() => new Singleton...
懒汉式(静态变量) 这种方式是在第一次调用`Instance`时才创建实例,但不保证线程安全。为确保线程安全,可添加`lock`关键字。 ```csharp public sealed class Singleton { private static Singleton instance;...
- 避免重复初始化变量:重复初始化会浪费资源,应当确保变量只在需要时初始化。 - JAVA + ORACLE整合:优化数据库查询,使用预编译语句,减少网络传输和解析时间。 - I/O流操作:合理使用缓冲区,避免频繁的读写...
但是,由于WinForms窗体需要在UI线程上初始化,因此通常会在窗体类的静态方法中初始化实例。 3. **公共访问点**:提供一个公共的静态方法,如`GetInstance()`,用于获取窗体的唯一实例。 ```csharp public static ...
2. 在实现文件中,我们使用`@synchronized`关键字确保线程安全,同时初始化静态实例变量。 ```objc @implementation Singleton static Singleton * _sharedInstance = nil; + (instancetype)sharedInstance { @...
3. **延迟初始化**:Java允许我们使用`lazy initialization`策略,这意味着一个变量或资源只有在真正需要时才会被初始化。这通常通过使用`null`检查或双重检查锁定(Double-Checked Locking)来实现,以提高性能和...
3. 初始化父类的非静态成员和非静态初始化块。 4. 调用父类的构造函数。 5. 初始化子类的非静态成员和非静态初始化块。 6. 调用子类的构造函数。 在给定的示例代码中,当执行`ChildClass cc = new ChildClass();`时...
理解这些默认值对于避免在编写程序时出现意外行为至关重要,特别是在处理大量数据或者初始化变量时。 总的来说,Singleton类的使用可以确保资源的有效管理和控制,构造函数则是创建和初始化对象的关键工具,而掌握...
Lazy Initialization Holder Class(延迟初始化持有类) 另一种实现线程安全的单例模式的方法是使用静态内部类。这种方式利用了Java类加载机制的特性来保证初始化的线程安全性,同时又延迟了单例的初始化过程。 `...