Passive instantiation

zhaozj2021-02-12  171

Passive instantiation - the balance between performance and resource occupation

Translator Note: I haven't intended to translate this article, but when I started the code and bug fix, I found out the problem in the program code. So I translated this article. For everyone Reference, where the translation mistakes are also asked, please advise. Thank you!

SUMMARY: Since the birth of the computer, in order to avoid waste of these useful resources, software performance and resource consumption, it is always a problem, and it may sometimes sacrifice some software performance to achieve this. This topic explores a method of reducing memory consumption by delaying the creation of objects to the system in Java programming. (2400 words)

When the memory on the 8-bit computer motherboard is from 8KB to 64kB, we are exciting at the moment, it seems that it will happen to see the resource we use now, and it is still increasing application system. System procedures that have been able to write to those poor memory in the past can be surprised. Although we have more memory resources now, we can learn a lot of valuable experience from the technologies based on many constraints.

In addition, Java programming is not only written some Applets and applications deployed to your PC or workstation. It has inserted into the market area of ​​embedded systems. The memory resources and computing power of the current embedded system are still very limited. Therefore, many old problems faced in the past have reappeared in front of the Java programmer involved in the field of embedded equipment.

Balance resource and performance These factors are a very exciting design topic: in the design and development of embedded systems, no solution is perfect. We must accept this fact. Therefore, we need to understand some technical types, which is to make a better technique that the balance we mentioned above is in an existing deployment platform.

Among them, an effective technology that avoids memory consumption is passive instantiation, and Java programmers have found a useful place in actual work. Using passive instantification technology, the program will create him when certain resources are first used. --- This is equivalent to released useful memory space. In this topic, we explore passive instantiated technologies in two aspects of the creation of class loads and objects, and we have special considerations for the case of single case mode. These materials come from my work Java actual combat: The ninth chapter in Design Styles & IDioms for Effective Java.

Active initialization and passive initialization: an example

If you are familiar with the Netscapse web browser and have used 3.x and 4.x. Then you must notice that the Java runtime mechanism is different at the time of loading. When Netscape 3.0 is started, if you pay attention to the flash screen, you will find that he is loading various resources, including Java. However, in Netscape 4.x, the browser does not load the Java runtime mechanism - - It will not be loaded until you run the web page including the tag. These two solutions reflect the active instantiation (loading it, in cases) and passive instantiation (until he is requested, or it will not be used at all) technology.

There are some shortcomings for both solutions. On the one hand, a resource is often mounted potentially wasting valuable memory resources, and if these loaded resources are not used at all during the session. On the other hand, for passive initialization, if the previous resources are not loaded, you have to pay a certain load time when the resource is requested.

Passive instantification as a resource holding strategy is passively instantiated in Java can be divided into two categories. . Class passive loads. Object passive creation

Class passive load Java runtime mechanism has embedded passive instances of classes. Only when the class is first referenced, it will be loaded into memory (also available from the web server from the web server) MyUtils.classmethod (); // first call to a static class method vector v = new vector (); The passive load of the // First Call to Operator New class is a very important feature in a Java operating environment. In some cases, it reduces the use of memory. In a session period, if a part of the program has never been executed, the class referenced in that program will not be loaded. The passive creation of the object passively created objects is closely linked. In a type that never loaded, the first time uses the New keyword, the Java runtime mechanism will load it. The passive creation of the object relative to the passive loading of the class can degrade memory consumption more than the class. To introduce the object passive creation this concept, let me see a simple code example. This example is mainly a Frame to display an error message using MessageBox. public class MyFrame extends Frame {private MessageBox mb_ = new MessageBox (); // private helper used by this class private void showMessage (String message) {// set the message text mb_.setMessage (message); mb_.pack (); MB_.show ();}}

In this example, when a MyFrame instance is created, MB_ is also created. If there is an object in the object being created, you need to be created, then the recursive creation of the object will appear. Any variables that are instantiated or assigned to MessageBox are allocated in the system's HEAP. If in a session period, MyFrame's instance is not used to display the error message, we waste there's unnecessary memory. In this quite simple example, we can't find how significant advantages created by passive objects, but if it is a more complex class, many other classes are used in this class. At this time, you may need to instantiate these classes. Then these potential memory consumption is quite obvious.

Next, please see the passive implementation method of the example mentioned above. In this method, the object MB_ is instantiated when the ShowMessage () method is called (that is, until it is truly required by the program. ) public final class MyFrame extends Frame {private MessageBox mb_; // null, implicit // private helper used by this class private void showMessage (String message) {if (mb _ == null) // first call to this method mb_ = new Messagebox (); // set the message text mb_.setMessage (MB_.Pack (); MB_.Show ();}} If you carefully observe the showMessage () method, you will see that we first detect if instance variables MB_ is equal to NULL. For the case where MB_ does not instantiate it, the Java runtime mechanism has been processed for us (the translator Note: The variable of the reference type is NULL). So, We can continue to actually execute the program by creating a MessageBox instance object. For all the calls for the showMessage () method, the instance variable MB_ is not equal to NULL, so it will skip the object to create this step directly to use existing instances. .

An example of a real world

Now let's take a closer look, in this example, passive instantiation plays a very important role in reducing the resources used by the program.

Suppose we need to write a system at the request of the customer, which allows the user to classify the image in the file system and provides a tool to browse the thumbnail or full image. Then we first thought that it is to write a class to load pictures in its construct.

public class ImageFile {private String filename_; private Image image_; public ImageFile (String filename) {filename_ = filename; // load the image} public String getName () {return filename_;} public Image getImage () {return image_;}}

In the above example, ImageFile uses a positive solution when instanting the Image object. This design guarantees that the Image object is immediately taken into effect when the getImage () method is called for use. However, this implementation is not only slow in speed (there are many pictures in the folder), and this design will consume too much memory. In order to avoid this potential problem, reduce memory consumption, we abandon the performance benefits of this instant access method. You may have already guessed, we can use passive instance to achieve our requirements.

Below is a modified ImageFile class, which uses the same solution as the MessageBox instance variable in the MyFrame class.

public class ImageFile {private String filename_; private Image image_; // = null, implicit public ImageFile (String filename) {// only store the filename filename_ = filename;} public String getName () {return filename_;} public Image getImage ( ) {If (image _ == null) {//first call to getimage () // load the image ...} Return Image_;}}

In this release, only when the getImage () method is called, the image_ instance variable is loaded. The purpose of this change is to reduce the number of integral memory usage and the number of launching operations, and the cost we pay for it is to load it when the first request is requested. This is another feature of passive instantiation - use in memory Performance mode (Proxy Pattern) in the contextual environment of the constraint.

The passive initialization strategy shown above is enough for us. But immediately, you will see such a design if you need to change in a multi-thread context environment.

Passive instantiation in single case mode

Let's take a look at a single example mode. Below is the general expressive technique of this mode in Java.

{Private Singleton ()} static private singleton instance_ = new singleleton (); static public singleton instance () {return instance_;} // public methods}

In this preferred single sample version, we declare and initialize the instance_ domain member: static final singleton instance_ = new singleleton ();

More familiar with "Four Gang" (Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides Four DESIGN PATTERNS: Elements of Reusable Object-Oriented Software "The reader of the C single case mode implements the reader may Surprised to we did not postpone the initialization movement of the variable instance_ to the instance () method called. Therefore, they will think that they should use passive instantiation, like this:

Public static singleleton instance () {

IF (instance _ == null) // lazy instantiation

Instance_ = new singleleton (); returnial_;

The code listed above is the original seal from the C single case example of "Tour", and this method is often said to be a model of Java program. If you have been familiar with this way and surprised me to list Java's single case mode, you even think that I don't have to do it in Java. Once you don't think about the runtime environment of the respective language, you will directly transplant the code from a language to another, then the above confusion is very common. } Instead, the C single case mode of the "Four Help" is used to use passive initialization because the order of static initialization of the object cannot be guaranteed at the runtime. (Please refer to SCTT Meyer Sample Mode in C ) In Java, we don't have to worry about this.

Since the Java runtime is a handling method for the initialization of the class loading and static STATIC instance variable (the translator's Note: The static member in the class load time class is automatically initialized by the non-static member variables and can only be initialized once), in a single case The passive initialization in the pattern is not necessary in Java. Previous, we mentioned how could be loaded. At runtime, a class with only the public static method is loaded when his method is called by the first time. Just like Singleton S = Singleton.instance ();

The first call in the program () will force the Java to load class Singleton when the Java is running. Since the instance_ variable is declared as static static.java runtime, this variable is initialized after successfully loading the class. So guarantees that the Singleton.instance () method can return a single example of complete initialization, don't you know if you understand?

Passive Initialization Hazard When using a specific single case mode in Java's specific single-case model implementation not only unnecessary, but also causes dangerous in the context of multi-threaded applications. Let us consider the passive instance of the Singleton.Istance () method, if there are two or more stand-alone threads that are trying to get the reference to the object via the instance () method. If one of the threads first execute the IF (instance _ == null) judgment statement, but before she executes the instance_ = new singleton () statement, another thread has also entered this method and successfully executed IF (Instance _ == Judgment of NULL, dirty data occurs at this time.

Once we have just appeared, once we have appeared, the consequences of these are one or more Singleton objects were created. Assume that if your Singleton class is responsible for connecting the database or remote server, it can really become troublesome. This problem is a simple solution to use the synchronized keyword to prevent simultaneous access to a multi-thread.

Synchronized static public instance () {...} However, there is a problem in a multi-threaded program that is widely implemented, it will block synchronous access to the instance () method. Moreover, a synchronization method is usually slower than that of calling an asynchronous method. We really need synchronization strategy should not cause unnecessary blocking. Fortunately, we have such a solution. That is what we said "Double Access Mode" (Double-Check Idiom)

Double access mode uses a double access mode to protect the method of using passive instance, the following is our specific implementation method public static singleleton instance () {

IF (Instance_ == Null) // Don't Want To Block Here

{

// Two or more thets might be here !!! Synchronized (Singleton.CLASS)

{

// must check again as one of the

// Blocked Threads Can Still Enter if (Instance_ == Null)

Instance_ = new singleleton (); // Safe

}

}

Return instance_;}

When Singlet is built, multiple threads call the instance () method, the "Double Access" method can improve performance by synchronization. Once the object is instantiated, the instance_ variable is no longer equal to NULL, but also avoid blocking Other synchronous callers.

Using multi-threads in Java will make the system become more complicated. In fact, synchronization this topic is very broad, Doug LEA has already written a book for its book: Concurrent Programming in Java. If you are now involved in synchronization programming. Then I suggest that you should look at this book before you start writing relying on multithreading, you better look at this book. Summary: We usually develop some agreements to meet customer needs and expectations or more effectively utilize limited resources. Understanding Java implements passively instantiated technologies, plus the rich features and runtime environments provided by Java languages ​​(JRE), which can help you design efficient, beautiful, fast software systems. In-depth investigation and evaluation materials on active and passive implementation can be found in our work.

转载请注明原文地址:https://www.9cbs.com/read-6191.html

New Post(0)
CopyRight © 2020 All Rights Reserved
Processed: 0.029, SQL: 9