On the single case design pattern in Java programming

When writing software, you often need to use the print log function, which can help you debug and locate problems. After the project goes online, it can also help you analyze data. But Java comes with a native system out. The println () method is rarely used in real project development, and even code checking tools such as findbugs think that system out. Println () is a bug.

Why is system. Java a novice artifact out. Will println () be despised in real project development? In fact, as long as you analyze it carefully, you will find many disadvantages. For example, it is uncontrollable, and all logs will be printed as usual after the project is launched, so as to reduce the operation efficiency; Or the log cannot be recorded to the local file. Once the print is cleared, the log will never be found again; Or if the printed content is not distinguished by tag, it will be difficult for you to identify the class in which this line of log is printed.

Your leader is not a fool. Use system out. He is also clear about the disadvantages of println (), so his task for you today is to create a logging tool class to provide better logging functions. However, your leader is not bad. It doesn't let you implement a powerful logging tool class with various functions at the beginning. You only need a logging tool that can control the printing level.

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

To print logs through this class, you only need to control the level, and you can freely control the printed content. For example, if the project is in the development stage, set the level to debug, so that all log information will be printed. If the project is online, 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 the level to error. If your project is a client version and you don't want any logs to be printed, you can set the level to noting. When printing, you only need to call:

You can't wait to introduce this tool to your leader. After listening to your introduction, your leader said, "good job. In the future, everyone will use the tool you wrote to print the log!"

But before long, your leader found you to give feedback. He said that although this tool is easy to use, printing does not distinguish objects. Here, every time you need to print logs, you need to create a new logutil, which takes up too much memory. I hope you can change this tool to be implemented in singleton mode.

You think what your leader said is very reasonable, and you want to take this opportunity to practice using design patterns, so you wrote the following code (PS: I implemented the code myself, and I didn't pay attention to thread synchronization at first):

First, privatize the logutil constructor, so that the new keyword cannot be used to create an instance of logutil. Then, a private static variable of slogutil is used to save the instance, and a public getInstance method is provided to obtain the instance of logutil. In this method, it is judged that if slogutil is empty, a new instance of logutil will be created, otherwise slogutil will be returned directly. This ensures that only one instance of logutil exists in memory. Singleton mode completed! At this time, the code for printing the log needs to be changed as follows:

When you show this version to your leader, he smiles and says, "although it seems that the singleton mode has been implemented, there are still bugs. You are full of doubts. Isn't singleton mode implemented in this way? What other bugs will there be?

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

If two threads are executing the getInstance method at the same time, the first thread has just executed line 2 and has not executed line 3. At this time, the second thread will find that slogutil is still null and enter the if judgment. In this way, your singleton mode fails because two different instances are created. You suddenly realize it, but you think very fast and immediately think of a solution. You just need to add a synchronization lock to the method. The code is as follows:

In this way, only one thread is allowed to execute the code in getInstance at the same time, which effectively solves the above situation of creating two instances. Your leader looked at your new code and said, "well, good. This does solve the possibility of creating two instances, but there is still a problem with this code."

You're nervous. How can there be a problem?

Your leader smiles: "Don't worry, it's not a bug this time, but the performance can be optimized. Look, if I add a synchronized method to the getInstance method, I will be affected by the synchronization lock every time I execute the getInstance method, which will reduce the operation efficiency. In fact, I just need to add the synchronization lock when I create the logutil instance for the first time. Let me do it Teach you how to optimize it better. "

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

After the code is changed to this way, it will enter line 3 only when slogutil has not been initialized, and then add the synchronization lock. Once slogutil is initialized, it will never go to line 3 again. In this way, the execution of getInstance method will no longer be affected by synchronization lock, and the efficiency will be improved to a certain extent. You can't help admiring that this method is so clever. It's really smart to think of it.

Your leader immediately became modest: "this method is called double check locking. I didn't think of it. You can check it online for more information."

In fact, I'm more used to using hungry man mode to implement singleton in Java

Lazy style is characterized by delayed loading, and instances are not loaded until they are used

The hungry type is characterized by loading at the beginning, so it can be returned directly every time it is used (I prefer this one, because there is no need to consider too many thread safety issues. Of course, the lazy type can solve the synchronization problem through the above-mentioned double locking)

The code to realize logging in Chinese style is as follows:

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>