Design Mode: Singleton)

Source: Internet
Author: User

Design Mode: Singleton)

Wu jian2013-06-05

OriginalArticle, Reprint must indicate the source: http://www.cnblogs.com/wu-jian

 

Preface

The Singleton mode is one of the first design patterns that we know and often use. It was a long time ago that we wanted to write it down, but it was delayed due to insufficient preparation for some details. This article uses examples andCodeThe requirements, principles, and implementation of the singleton mode are analyzed, and the single-case mode and Performance Optimization in B/S development are discussed. I also hope to help my friends who learn the design model. At the same time, my personal abilities are limited. please correct me if there are any deficiencies in this article.

 

Why Singleton mode?

First, let's take a look at the definition of Singleton mode: Singleton mode is an object creation mode, which has the following features:

1. Ensure that one class has only one instance

2. You must create your own unique instance.

3. Provide global access points for a unique instance

The Singleton mode has many application scenarios, such as printers.ProgramA simple explanation of the problem: if there is a printer, we have written a print program. If this printer can be used everywhere for new (), a new is used, and B New is used, before printing a, B starts printing again. Therefore, the printer program must use the singleton mode, that is, only one object can communicate with the printer. If both A and B are printed, queue in the singleton object.

To use the simplest example to understand a Singleton, I think Obama is more representative: The Singleton model is like the president of the United States. The President of the United States can only have one. If there are multiple? It is estimated that the Chinese people, especially the North Korean people, will be happy.

 

Implementation of the singleton Mode

The Singleton mode can be implemented in two ways: ELE. Me and lazy. The Code is as follows:

 //  Ele. Me      Public   Sealed   Class Hungryman {  //  Class instantiation during loading          Private   Static Hungryman minstance = New  Hungryman ();  //  Private Constructor          Private  Hungryman (){}  //  Provides global access points in simple factory Mode          Public   Static Hungryman instance {  Get { Return  Minstance ;}}} 

Ele. Me is the easiest way to implement singleton. It is also a typical space change time. When a class is loaded, an instance is created, regardless of whether the instance needs to be used or not. When the instance is used in the future, no judgment is made, saving the running time but occupying the space. Some frequently used objects are suitable for the hungry Chinese.

 

Perfect hunger

If you are not perfectionist, you can ignore this section because the code in this section cannot improve performance in most cases.

When using the hunger mode, C # does not guarantee the creation time of the instance, as follows:

 
Private StaticHungryman minstance =NewHungryman ();

Static fields may be assigned values when the class is loaded or before being called. In short, we cannot determine when to create a class instance. As a result, the perfectionist suggested that the uncertainty caused by this CLR mechanism will lead to performance loss. Can minstance be initialized instantly before it is called? This can save memory overhead for a period of time. So the optimized version of ELE. Me is as follows:

//  Perfect hunger      Public   Sealed   Class  Perfecthungryman {  Private   Static   Readonly Perfecthungryman minstance = New  Perfecthungryman ();  Private  Perfecthungryman (){}  //  Implement delayed initialization through static Constructor         Static  Perfecthungryman (){}  Public   Static  Perfecthungryman instance {  Get { Return  Minstance ;}}} 

For example, the comments in the code implement class delay initialization through the static Constructor (that is, initialization before the call ). Comparing the intermediate code generated by the two classes, we can see that there is only one difference: perfecthungryman has one less feature than hungryman: beforefieldinit, that is, the static constructor has restrained the beforefieldinit feature, this feature affects class initialization. Obtain Il, as shown in:

Classes that contain beforefieldinit will be initialized by the CLR when appropriate; classes that do not contain beforefieldinit will be forcibly initialized before the call. As described at the beginning of this section, in most cases, the initialization of the beforefieldinit delay class can not improve the performance, or the performance will be slightly improved.

So unless in special cases, we don't have to pick up sesame seeds and drop the watermelon.

 

Implementation of the singleton mode (non-thread security)

The lazy is created only when necessary, as shown in the following code:

 //  Lazy      Public   Sealed   Class  Lazyman {  Private   Static Lazyman minstance = Null  ;  Private  Lazyman (){}  //  Instantiate as needed         Public   Static  Lazyman instance {  Get  {  If (Minstance = Null  ) Minstance = New  Lazyman ();  Return  Minstance ;}}} 

But there is a problem in the code, that is, when two or more requests are called at the same time in a multi-threaded environment, multiple objects will be created, which violates the basic principles of Singleton.

 

Loose in thread security

//  Loose in thread security      Public   Sealed   Class  Multilazyman {  Private   Static Multilazyman minstance = Null  ;  Private   Static   Readonly   Object Synclock = New Object ();  Private  Multilazyman (){}  //  Instantiate as needed          Public   Static  Multilazyman instance {  Get  {  //  Ensure single-thread access                  Lock  (Synclock ){  If (Minstance =Null  ) Minstance = New  Multilazyman ();  Return  Minstance ;}}}} 

The implementation of the above Code is thread-safe. First, a static read-only process auxiliary object is created. Lock ensures that when a thread is located in the critical section of the Code, another thread cannot enter the critical section (synchronous operation ). If other threads attempt to enter the locked code, they will wait until the object is released. This ensures that multiple object instances are not created under multiple threads.

This implementation ensures the uniqueness of instances in a multi-threaded environment. However, from the code, we can find that each thread occupies lock. If a web program has 100 requests at the same time, it will lock 100 times, and there will always be queues. In terms of performance, this method has low efficiency and high performance overhead.

 

Perfect lazy

In a multi-threaded environment, we only need to use lock when creating an instance for the first time to ensure that the instance is unique. After the instance is created, it can be shared by everyone. Add a line of small judgment, as shown in the following code:

 // Perfect lazy      Public   Sealed   Class  Perfectlazyman {  //  The volatile keyword indicates that a field can be modified by multiple concurrent threads.  //  Fields declared as volatile are not restricted by Compiler Optimization (assuming that they are accessed by a single thread.  //  This ensures that the field displays the latest value at any time.          Private   Static   Volatile Perfectlazyman minstance =Null  ;  Private   Static   Readonly   Object Synclock = New  Object ();  Private  Perfectlazyman (){}  Public   Static  Perfectlazyman instance {  Get  { //  The lock is performed only when the instance is created for the first time.                  If (Minstance = Null  ){  //  Ensure single-thread access                      Lock  (Synclock ){  If (Minstance = Null  ) Minstance = New Perfectlazyman ();}}  Return  Minstance ;}}} 

OK. It's a perfect lazy to be judged by one hand.

If you look up the information, this manual judgment actually has a seemingly profound terminology: Double Check Idiom)

The term is changed from C to Java and then from Java to C #. I am lucky to have read the relevant details in macro's "Java and patterns". By the way, I also recommend this book. Although it is a bit thick, it is still well written. If the author has less dogmatism, this book should be a model for Chinese design patterns.

 

Lazy <t>

 //  Lazy <t>      Public   Sealed   Class  Genericlazyman { Private   Static   Readonly Lazy <genericlazyman> minstance = New Lazy <genericlazyman> () => New  Genericlazyman ());  Private  Genericlazyman (){}  Public   Static  Genericlazyman instance {  Get  { Return  Minstance. Value ;}}} 

Lazy <t> is an encapsulation provided by. NET Framework 4.x for large object delay loading. It provides a series of convenient functions and thread security, which is not described here.

Lazy <t> reference: http://msdn.microsoft.com/en-us/library/dd997286 (vs.100). aspx

 

Singleton mode and Performance

In B/S development, I think everyone has written the following code:

 
Protected VoidPage_load (ObjectSender, eventargs e) {businessobject=NewSomewhere. businessobject (); businessobject. dosomething ();}

Create a Business Object and call the object method to complete some operations.

Because. net, Java, and other advanced languages have built-in garbage collection mechanisms. We can take care of the concurrent memory overhead by GC (garbage collection, garbage collection, therefore, the above Code won't be faulty in most cases, so that we gradually forget concurrency, memory, and performance.

B/S development is intended for multiple users to process concurrent requests. The new object in page_load is used for each request. When 1000 people visit a page at the same time, we actually put 1000 new objects in the memory. If it happens that this object has more than 10 MB, that means the memory overhead will be greater than 10 Gb. This is a terrible number, but we don't often encounter 1000 concurrent and 10 m objects. Of course, we also have garbage collection to escort.

Below I have simulated an object of around 100 MB, with concurrency. Let's look at the following CPU and memory curves:

First, the CPU usage soared, and then the memory overhead experienced regular peaks and valleys. Obviously, each peak represents the beginning of garbage collection, and each bottom represents the end of garbage collection. Although garbage collection brings us convenience, it is also known to all for its performance loss. Attached to this testSource code:

 Namespace  WUJian. designmodel. Singleton {  Public   Class  Testobject {  // Load a m Image          Public  Testobject (){  This . Mdata = system. Drawing. image. fromfile (httpruntime. appdomainapppath + @"  App_data \ 1500k.jpg  "  );}  Private  System. Drawing. Image mdata;  Public  System. Drawing. Image Data {  Get {Return   This  . Mdata ;}  Set { This . Mdata = Value ;}}}  Public   Partial   Class  Staticdemo: system. Web. UI. Page {  Protected   Void Page_load ( Object  Sender, eventargs e) {testobject OBJ = New  Testobject (); response. Write (  "  Image Width is  " + Obj. Data. Width + "  Px  "  );}}} 

 

Next let's take a look at the single-instance mode of the same 100 m object, concurrency:

The memory overhead is a straight line with no peaks and valleys, no garbage collection, and almost no impact on the number of concurrency. 100 of concurrency and 1000 of concurrency are identical in the memory overhead. Paste the code changes section:

 Public   Partial   Class Staticdemo: system. Web. UI. Page {  //  Singleton Mode          Private   Static   Readonly Testobject OBJ = New  Testobject ();  Protected   Void Page_load ( Object  Sender, eventargs e) {response. Write (  "  Image Width is " + Obj. Data. Width + "  Px  "  );}} 

 

The example is very simple, and its purpose is only to arouse some thinking. Do you care about the memory overhead of reusable objects? Have you become a prisoner of garbage collection?

 

Download demo

Demo environment: Visual Studio 2012,. NET Framework 4.5

Click to download demo

Note: jmeter,: http://jmeter.apache.org/

. Net memory Analysis Using CLR profiler,: http://search.microsoft.com/en-us/DownloadResults.aspx? Q = CLR % 20 profiler

 

References:

Java and Mode

Head first design model

Uncle Tom: Don't let the interviewer ask you a single example.

 

<Full text>

 

Author: Wu Jian
Source: http://www.cnblogs.com/wu-jian/
The copyright of this article is shared by the author and the blog Park. You are welcome to repost it, but you must specify the source and provide the original article connection clearly on the article page. Otherwise, you will be held legally liable.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.