Java Design Pattern Analysis-singleton

Source: Internet
Author: User

Reprinted please indicate the source: http://blog.csdn.net/sinyu890807/article/details/8860649

When writing software, you often need to use the log printing function, which can help you debug and locate problems. After the project is launched, it can also help you analyze data. However, Java Native systems. out. the println () method is rarely used in real project development. Even code check tools such as findbugs think that system is used. out. println () is a bug.

Why is system. Out. println (), a new-starter Java artifact, deprecated in real project development? In fact, as long as you analyze it carefully, you will find many drawbacks. For example, if it is not controllable, all logs will be printed as usual after the project is launched, reducing the running efficiency. Or, you cannot record the logs to local files. Once the printing is cleared, the log will no longer be found; or the printed content will not be differentiated by tags. It is difficult to identify the class in which the log is printed.

Your leader is not a dumb. Use System. out. he knows all the drawbacks of println (). Therefore, the task he gave you today is to create a log tool class to provide better log functions. However, your leader is not bad. It didn't enable you to implement a powerful log tool class with various functions at the beginning. You only need a log tool that can control the printing level.

This requirement is not difficult for you. You started to write it immediately and completed the first version soon:

public class LogUtil {public final int DEGUB = 0;public final int INFO = 1;public final int ERROR = 2;public final int NOTHING = 3;public int level = DEGUB;public void debug(String msg) {if (DEGUB >= level) {System.out.println(msg);}}public void info(String msg) {if (INFO >= level) {System.out.println(msg);}}public void error(String msg) {if (ERROR >= level) {System.out.println(msg);}}}

By using this class to print logs, you only need to control the level to freely control the printed content. For example, if the project is in the development stage, set level to debug, so that all log information is printed. If the project is launched, you can set the level to info, so that you can only see the log printing of info and above. If you only want to see the error log, you can set level to error. If the project you are developing is a client version and you do not want to print any logs, you can set level to nothing. When printing, you only need to call:

new LogUtil().debug("Hello World");

 

You can't wait to introduce this tool to your leader. After hearing your introduction, your leader said, "well, you will use this tool to print logs in the future !"

It wasn't long before your leader found you to report the problem. He said that although this tool is easy to use, it does not differentiate objects to print such a thing. Here, every time you need to print logs, a new logutil will be generated, which occupies too much memory, we hope you can change this tool to the singleton mode.

You think what your leader says makes sense, and you want to take this opportunity to practice the design pattern, so you wrote the following code:

public class LogUtil {private static LogUtil sLogUtil;public final int DEGUB = 0;public final int INFO = 1;public final int ERROR = 2;public final int NOTHING = 3;public int level = DEGUB;private LogUtil() {}public static LogUtil getInstance() {if (sLogUtil == null) {sLogUtil = new LogUtil();}return sLogUtil;}public void debug(String msg) {if (DEGUB >= level) {System.out.println(msg);}}public void info(String msg) {if (INFO >= level) {System.out.println(msg);}}public void error(String msg) {if (ERROR >= level) {System.out.println(msg);}}}

First, privatize the logutil constructor, So that you cannot use the new keyword to create a logutil instance. Then, an slogutil private static variable is used to save the instance, and a public getinstance method is provided to obtain the logutil instance. In this method, if slogutil is empty, A new logutil instance is created. Otherwise, slogutil is returned. This ensures that only one logutil instance exists in the memory. The Singleton mode is complete! The log printing code needs to be changed to the following method:

LogUtil.getInstance().debug("Hello World");

When you show this version to your leader, he smiled and said, "although this seems to have implemented the singleton mode, there are still bugs.

 

Are you confused that the singleton mode is not implemented in this way? What other bugs will there be?

Your leader prompts you That the singleton mode is used to make this class have only one instance in the memory, but have you considered printing logs in multiple threads? As shown in the following code:

public static LogUtil getInstance() {if (sLogUtil == null) {sLogUtil = new LogUtil();}return sLogUtil;}

If two threads are executing the getinstance method at the same time, the first thread has just finished executing 2nd rows but has not yet executed 3rd rows. At this time, the second thread has executed 2nd rows, it will find slogutil or null, so it enters the if judgment. In this way, your Singleton mode fails because two different instances are created.

 

You suddenly realized, but you thought very quickly and immediately came up with a solution. You only need to add a synchronization lock to the method. The Code is as follows:

public synchronized static LogUtil getInstance() {if (sLogUtil == null) {sLogUtil = new LogUtil();}return sLogUtil;}

In this way, only one thread is allowed to execute the code in getinstance at the same time, which effectively solves the above situation where two instances will be created.

 

After reading your new code, your leader said, "Well, it's good. This does solve the possibility of creating two instances, but this code still has a problem ."

Why are you still having problems when you get nervous?

Your leader smiled: "You don't have to worry. This is not a bug, but performance can be optimized. You can see that if a synchronized is added to the getinstance method, the synchronization lock will be affected every time I execute the getinstace method. This will reduce the running efficiency, in fact, you only need to add the synchronization lock when creating the logutil instance for the first time. I will teach you how to optimize it better ."

First, remove the synchronized keyword from the method declaration and add it to the method body:

public static LogUtil getInstance() {synchronized (LogUtil.class) {if (sLogUtil == null) {sLogUtil = new LogUtil();}return sLogUtil;}}

 

The effect is exactly the same as adding synchronized directly to the method. Then add a judgment on the outside of synchronized, as shown below:

public static LogUtil getInstance() {if (sLogUtil == null) {synchronized (LogUtil.class) {if (sLogUtil == null) {sLogUtil = new LogUtil();}}}return sLogUtil;}

After the code is changed to this type, slogutil enters row 3rd only when it is not initialized, and the synchronization lock is added. When the initialization of slogutil is complete, no more than 3rd rows will be taken. In this way, the execution of the getinstance method will not be affected by the synchronization lock, and the efficiency will be improved.

 

You can't help but admire it. This method is really clever. It's so clever to come up with it.

Your leader immediately becomes modest: "This method is called double-check locking, but it is not my idea. You can check more information on the Internet ."


Singleton: ensure that a class has only one instance, and provide a global access point to access it.

 

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.