- 浏览: 793418 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (651)
- Java (39)
- Java 初学者小问题 (66)
- 设计模式 (7)
- 项目管理 (3)
- 数据库 (1)
- 算法 (2)
- Java practices (6)
- Effective Java2读书笔记 (78)
- Linux (2)
- programming ruby 读书笔记 (5)
- Core Java Ninth Edition Volume I 读书笔记 (15)
- Pro Git 读书笔记 (12)
- Git (3)
- Maven in Action 读书笔记 (20)
- Web (12)
- 非技术类书籍 (11)
- 电影 (40)
- Web Cache (1)
- jquery (0)
- 历史 (4)
- Dive Into HTML5 读书笔记 (13)
- 三国演义小学毕业考 (79)
- 高效能人士的7个习惯 读书笔记 (12)
- Java Performance 读书笔记 (3)
- Protocol Buffer 学习笔记 (6)
- Mongo DB 学习笔记 (7)
- Morphia 学习笔记 (7)
- Algorithms -- Princeton 学习笔记 (13)
- String研究 (10)
- Hadoop: The Definitive Guide 读书笔记 (3)
- Java与模式读书笔记 (5)
- Date研究 (3)
- The Roman Empire 听课笔记 (4)
- Algorithms -- Standford 学习笔记 (16)
- Core Java Ninth Edition Volume II 读书笔记 (9)
- Thinking in Java 4th Edition 读书笔记 (21)
- Node : Up and Running 学习笔记 (5)
- Eloquent Javascript (8)
- Smashing Node.js 读书笔记 (1)
- Algorithms II -- Standford 学习笔记 (19)
- Algorithm II -- Princeton 学习笔记 (14)
- 网络安全 (2)
- Javascript (4)
- 正则表达式 (1)
- JAVA 7/8 (15)
- JVM (10)
- NodeJS (1)
- 鸟哥的linux私房菜读书笔记 (14)
- Web Service (1)
- The art of programming (9)
- Introduction to Algorithm 读书笔记 (4)
- Java 源码阅读 (0)
- Spring in Action 读书笔记 (2)
- Java Network Programming 读书笔记 (2)
最新评论
-
心存高远:
谢谢作者分享,刚好看到这里不太明白,现在茅塞顿开。不过runt ...
关于 Maven的传递依赖的理解 -
sxlkk:
851228082 写道甚至在某次技术会议现场遇到《Maven ...
关于 Maven的传递依赖的理解 -
851228082:
851228082 写道a----compile----b-- ...
第五章 坐标和依赖 -
851228082:
a----compile----b-----provided- ...
第五章 坐标和依赖 -
851228082:
甚至在某次技术会议现场遇到《Maven in action》的 ...
关于 Maven的传递依赖的理解
Lazy initialization is a performance optimization. It's used when data is deemed to be 'expensive' for some reason. For example:
- if the hashCode value for an object might not actually be needed by its caller, always calculating the hashCode for all instances of the object may be felt to be unnecessary.
- since accessing a file system or network is relatively slow, such operations should be put off until they are absolutely required.
Lazy initialization has two objectives :
- delay an expensive operation until it's absolutely necessary
- store the result of that expensive operation, such that you won't need to repeat it again
As usual, the size of any performance gain, if any, is highly dependent on the problem, and in many cases may not be significant. As with any optimization, this technique should be used only if there is a clear and significant benefit.
To avoid a NullPointerException, a class must self-encapsulate fields that have lazy initialization. That is, a class cannot refer directly to such fields, but must access them through a method.
The hashCode method of an immutable Model Object is a common candidate for lazy initialization.
Example 1
In this example, there are two fields with lazy initialization - fHashCode and fAwards.
import java.util.*; public final class Athlete { public Athlete(int aId){ //a toy implementation: fId = aId; fName = "Roger Bannister"; //fAwards is not set here! } //..elided /** Lazy initialization is used here; this assumes that awards may not always be of interest to the caller, and that for some reason it is particularly expensive to fetch the List of Awards. */ public List getAwards(){ if ( fAwards == null ) { //the fAwards field has not yet been populated //Here is a toy implementation List<String> awards = new ArrayList<String>(); awards.add( "Gold Medal 2006" ); awards.add( "Bronze Medal 1998" ); fAwards = awards; } return fAwards; } /** This style applies only if the object is immutable. Another alternative is to calculate the hashCode once, when the object is initially constructed (again, applies only when object is immutable). */ @Override public int hashCode(){ if ( fHashCode == 0 ) { fHashCode = HashCodeUtil.SEED; fHashCode = HashCodeUtil.hash(fHashCode, fId); fHashCode = HashCodeUtil.hash(fHashCode, fName); //self-encapusulated: fAwards is not referenced directly, //since it may be null: fHashCode = HashCodeUtil.hash(fHashCode, getAwards()); } return fHashCode; } // PRIVATE // private int fId; private String fName; private List<String> fAwards; private int fHashCode; }
Example 2
Here, the look up of the printers available to a desktop PC is treated as an expensive operation.
import java.util.Arrays; import java.util.List; import javax.print.DocFlavor; import javax.print.PrintService; import javax.print.PrintServiceLookup; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.standard.OrientationRequested; import javax.print.attribute.standard.Sides; /** Printing services available to a desktop client. */ public final class Printers { /** Print some plain text (perhaps internally converted to PDF). */ void printSomething(String aText, PrintService aPrinter) { //...elided } /** Return the list of printers that can print PDFs (double-sided, portrait).*/ List<PrintService> listAvailablePrinters(){ if(fAvailablePrinters == null){ //double-sided, portrait, for PDF files. PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet(); attrs.add(Sides.DUPLEX); attrs.add(OrientationRequested.PORTRAIT); //Expensive operation! This can take several seconds in some environments: fAvailablePrinters = Arrays.asList( PrintServiceLookup.lookupPrintServices(DocFlavor.INPUT_STREAM.PDF, attrs) ); } return fAvailablePrinters; } // PRIVATE /** Looked up once, the first time it's needed, and then stored using a static reference. If it was a non-static reference, then the list of available printers would not be looked up just once, but perhaps many times (once per 'Printers' object, and not once per loaded 'Printers' class). Self-encapsulate : If this class's implementation needs to reference this item, it must do so indirectly, by calling listAvailablePrinters(). */ private static List<PrintService> fAvailablePrinters; }
Example 3
Lazy initialization is particularly useful for GUIs which take a long time to construct.
There are several policies for GUI construction which a design may follow:
- always build - construct the window many times, whenever it is demanded, and do not cache the result.
- first-request build - construct the window once, when first requested. Cache the result for any further requests, should they occur.
- background build - construct the window once, in a low priority worker thread, when the system is initialized. Cache the result for any requests, should they occur.
Here is an example of the first-request style, in which the fEditor field has lazy initialization (see the actionPerformed method).
package hirondelle.stocks.preferences; import java.awt.event.*; import javax.swing.*; import java.util.*; import java.util.logging.*; import hirondelle.stocks.util.Args; import hirondelle.stocks.util.ui.StandardEditor; import hirondelle.stocks.util.ui.UiUtil; import hirondelle.stocks.preferences.PreferencesEditor; import hirondelle.stocks.util.Util; /** * Present dialog to allow update of user preferences. * * <P>Related preferences are grouped together and placed in * a single pane of a <tt>JTabbedPane</tt>, which corresponds to an * implementation of {@link PreferencesEditor}. Values are pre-populated with * current values for preferences. * *<P>Most preferences have default values. If so, a * <tt>Restore Defaults</tt> button is provided for that set of related * preferences. * *<P>Preferences are not changed until the <tt>OK</tt> button is pressed. * Exception: the logging preferences take effect immediately, without the need * for hitting <tt>OK</tt>. */ public final class EditUserPreferencesAction extends AbstractAction { /** * Constructor. * * @param aFrame parent window to which this dialog is attached. * @param aPrefEditors contains implementations of {@link PreferencesEditor}, * each of which is placed in a pane of a <tt>JTabbedPane</tt>. */ public EditUserPreferencesAction (JFrame aFrame, List<PreferencesEditor> aPrefEditors) { super("Preferences...", UiUtil.getEmptyIcon()); Args.checkForNull(aFrame); Args.checkForNull(aPrefEditors); fFrame = aFrame; putValue(SHORT_DESCRIPTION, "Update user preferences"); putValue(LONG_DESCRIPTION, "Allows user input of preferences."); putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_P) ); fPrefEditors = aPrefEditors; } /** Display the user preferences dialog. */ public void actionPerformed(ActionEvent event) { fLogger.info("Showing user preferences dialog."); //lazy construction: fEditor is created only once, when this action //is explicitly invoked if ( fEditor == null ) { fEditor = new Editor("Edit Preferences", fFrame); } fEditor.showDialog(); } // PRIVATE // private JFrame fFrame; private java.util.List<PreferencesEditor> fPrefEditors; private static final Logger fLogger = Util.getLogger(EditUserPreferencesAction.class); /** * Specifying this as a field allows for "lazy" creation and use of the GUI, which is * of particular importance for a preferences dialog, since they are usually heavyweight, * and have a large number of components. */ private Editor fEditor; /** * Return GUI for editing all preferences, pre-populated with current * values. */ private JComponent getPrefEditors(){ JTabbedPane content = new JTabbedPane(); content.setTabPlacement(JTabbedPane.LEFT); int idx = 0; for(PreferencesEditor prefEditor: fPrefEditors) { JComponent editorGui = prefEditor.getUI(); editorGui.setBorder(UiUtil.getStandardBorder()); content.addTab(prefEditor.getTitle() , editorGui); content.setMnemonicAt(idx, prefEditor.getMnemonic()); ++idx; } return content; } /** Called only when the user hits the OK button. */ private void saveSettings(){ fLogger.fine("User selected OK. Updating table preferences."); for(PreferencesEditor prefEditor: fPrefEditors) { prefEditor.savePreferences(); } } /** * An example of a nested class which is nested because it is attached only * to the enclosing class, and it cannot act as superclass since multiple * inheritance of implementation is not possible. * * The implementation of this nested class is kept short by calling methods * of the enclosing class. */ private final class Editor extends StandardEditor { Editor(String aTitle, JFrame aParent){ super(aTitle, aParent, StandardEditor.CloseAction.HIDE); } public JComponent getEditorUI () { JPanel content = new JPanel(); content.setLayout( new BoxLayout(content, BoxLayout.Y_AXIS) ); content.add( getPrefEditors() ); //content.setMinimumSize(new Dimension(300,300) ); return content; } public void okAction() { saveSettings(); dispose(); } } }
This article originates from http://www.javapractices.com/topic/TopicAction.do?Id=34
发表评论
-
Avoid clone
2010-10-31 12:07 988Avoid implementing clone. c ... -
Implementing Serializable
2010-10-28 11:40 969Do not implement Serializable l ... -
Immutable objects
2010-10-21 22:46 1014Immutable objects are simply ob ... -
Validate state with class invariants
2010-10-21 22:24 1373Class invariants are methods wh ... -
Copy constructors
2010-10-20 23:57 903Copy constructors : provide ...
相关推荐
Hibernate的延迟加载(Lazy Loading)和懒加载机制(Lazy Initialization)是优化ORM框架性能的重要策略。这个机制的主要目的是提高程序的效率,减少不必要的数据库交互,只在真正需要数据时才去加载它们。以下是对...
在.NET框架中,`Lazy<T>`是一个非常有用的类,它实现了延迟初始化(Lazy Initialization)模式。这个模式的主要目的是推迟对象的创建,直到第一次真正需要它时才进行实例化,这样可以提高程序性能,特别是对于那些...
在.NET框架中,`System.Lazy<T>`是一个强大的工具,用于实现延迟初始化(Lazy Initialization)。延迟初始化是一种设计模式,它推迟对象的创建或资源的加载,直到第一次真正需要它们时。这种方式可以提高程序的性能...
在Java并发编程中,双检锁(Double-Checked Locking)是一种用于减少同步开销的优化技术,尤其适用于懒加载(lazy initialization)的场景。本文将详细探讨双检锁的工作原理、潜在问题以及如何安全地实现它。 双检锁...
然而,有时我们希望某些bean在实际需要时才进行初始化,这就是所谓的“懒加载”(Lazy Initialization)。Spring Boot 2.2及更高版本引入了一个全局懒加载机制,允许用户通过配置开启整个应用的bean懒加载,以优化...
本主题探讨的是线程安全的单例模式实现,特别是饥饿模式(Starvation)和延迟加载(Lazy Initialization)两种策略。 首先,让我们理解什么是线程安全。在多线程环境下,如果一个类的实例可以被多个线程同时访问,...
在C#中,单例模式可以通过多种方式实现,如Eager Initialization(急切初始化)、Lazy Initialization(懒惰初始化)以及线程安全的懒惰加载等。本文将重点介绍C#中两种不同的单例模式实现方法:基于嵌套类的完全...
1. **经典懒汉式(Lazy Initialization)**: 这种方式是在第一次调用GetInstance方法时才创建实例。但是这种方式在多线程环境下可能存在问题,因为多个线程可能会同时创建单例对象。 ```csharp public class ...
在Java中,实现单例模式通常使用懒汉式(lazy initialization)或饿汉式(eager initialization)。懒汉式是在第一次调用getInstance()方法时才创建实例,而饿汉式则是在类加载时就创建实例。在上述代码示例中,使用...
2. 懒汉式(Lazy Initialization) 懒汉式是在首次调用时才进行实例化,因此也被称为延迟初始化。为了保证线程安全,C#提供了`System.Lazy<T>`类,可以实现线程安全的懒汉式单例。 ```csharp public sealed class ...
Lazy initialization holder class 模式是指使用类级的内部类来实现延迟加载,下面是代码示例: ```java public class Singleton3 { / * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 ...
1. **懒汉式(Lazy Initialization)**:这是最常见的实现方式,延迟实例化直到首次被请求时。这种方式既实现了单例,又避免了不必要的初始化。例如: ```csharp public sealed class Singleton { private static ...
懒汉式(Lazy Initialization)则是在第一次使用时才创建实例,但原始的实现方式不线程安全。为了解决这个问题,我们可以使用同步方法(Synchronized Singleton),但这会降低并发性能。双重检查锁定(Double-Check ...
这种方法的优点是可以做到 lazy initialization,但是如果类似逻辑很多的话,代码中到处充斥着类似代码,不优雅。 方案二:使用 DependsOn Spring 中的 DependsOn 注解可以保证被依赖的 bean 先于当前 bean 被容器...
- **Default Lazy Initialization**:若希望对所有 Bean 都应用懒加载,则可以在 `<beans>` 根节点中设置 `default-lazy-init="true"`。 - **初始化和销毁方法**:可以指定初始化和销毁方法来管理 Bean 的生命周期...
2. **懒汉式**(Lazy Initialization): - 懒汉式是在第一次真正需要单例时才进行实例化,实现了按需创建,节约了内存空间。 - 传统的懒汉式实现可能存在线程安全问题,需要在多线程环境中进行同步控制,如使用...
然而,当尝试通过Address对象获取其关联的Person集合时,会出现懒加载(lazy initialization)问题。默认情况下,JPA只会延迟加载集合,直到我们实际访问该字段时才去数据库获取数据。为了解决这个问题,我们可以将@...
4. **延迟加载(Lazy Initialization)**:通过`lazy-init`属性,可以控制Bean是否延迟初始化。如果设置为`true`,Bean将在第一次请求时才实例化。全局设置`default-lazy-init`可以让所有Bean默认延迟加载。 5. **...
当检测到循环依赖时,Spring会尝试通过预初始化(Lazy Initialization)和早周期引用(Early Reference)的方式来打破循环。 1. 预初始化:默认情况下,Spring的bean默认为懒加载(Lazy),只有在被请求时才会实例...
2. 懒汉式(Lazy Initialization):首次使用时才创建单例,线程不安全,需要配合同步机制。 3. 双重检查锁定(Double-Check Locking):兼顾延迟初始化和线程安全,是推荐的实现方式。 4. 静态内部类:利用类加载...