Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the Java singleton pattern

2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces the relevant knowledge of "how to realize the Java singleton pattern". In the operation of the actual case, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

The singleton pattern is to private the constructor of the class, and then leave only a static Instance function for external callers to call.

I. hungry Han style

Regardless of whether we use this object or not in the future, we create an instance of this object at the very beginning, load and initialize the class in JVM, let the virtual machine ensure thread safety, and return the created instance object when needed, so it is relatively hungry, so it is called hungry singleton.

/ / single case of hungry Chinese public class Hungry {/ / it may waste space private byte [] data1 = new byte [1024024]; private byte [] data2 = new byte [1024024]; private byte [] data3 = new byte [1024024]; private byte [] data4 = new byte [1024024]; private Hungry () {} private final static Hungry HUNGRY = new Hungry (); public static Hungry getInstance () {return HUNGRY Second, lazy style

When our class has too many variables, it is not suitable for hungry Chinese to create a class, and we initialize the class when we need it. This mode is called lazy style. For example, the static class initialization mode below.

Public class SingleInit {private SingleInit () {} / / defines a private class to hold an instance of the current class private static class InstanceHolder {public static SingleInit instance = new SingleInit ();} public static SingleInit getInstance () {return InstanceHolder.instance;}}

Third, the actual lazy style

The first edition: multithreaded unsafe mode, just simply judge whether it is initialized, initialize if not.

Class SingletonLazy {private static SingletonLazy instance = null; private SingletonLazy () {} / * * the singleton implemented by this method cannot be used in multithreading, and multiple lines can enter the if method at the same time, resulting in the generation of multiple singleton objects. * @ return * / public static SingletonLazy getInstance () {if (instance==null) {instance= new SingletonLazy ();} return instance;}}

The second version: when multiple threads enter the getInstance, grab the lock, but this method is not desirable, seriously affect the performance, each call must obtain the lock, seriously affect the performance.

Class SingletonLazy {private static SingletonLazy instance= null; private SingletonLazy () {} public static synchronized SingletonLazy getInstance () {if (instance==null) {instance= new SingletonLazy ();} return instance;}}

The third edition: double locking mechanism, there are two judgments

1. When calling, determine whether it is already non-empty, and return directly if it is initialized.

two。 Without initializing the AB, both threads acquire the class lock, A gets the B does not, and then A creates the object directly and releases the lock. However, if the object initialized by An is not assigned to the singleDcl of the main memory, B will still be created if the lock is acquired. if there is no if judgment, the index should be judged by if and the main variable should be set to volatile. Because we new out of the object if the object contains a lot of data content willing to data has not been created oh! So use volatile.

Public class SingleDcl {private volatile static SingleDcl singleDcl; / / ensure the visibility private SingleDcl () {} public static SingleDcl getInstance () {if (singleDcl==null) {/ / put into the lock code, first determine whether the synchronized (SingleDcl.class) {/ / class lock may appear that the AB thread is stuck here, A gets the lock, B waits for the lock. If (singleDcl==null) {/ / if the A thread is initialized, then complicate the variables to the resident thread through vloatile. / / if there is no singleDel = = null at this time, determine that the B process will execute the new statement singleDcl = new SingleDcl () again after the B process enters;} return singleDcl;}} destroy the singleton mode

First, use reflection to force access to the private constructor of the class to create another object

Public static void main (String [] args) {/ / get the class's explicit constructor Constructor construct = Singleton.class.getDeclaredConstructor (); / / accessible private constructor construct.setAccessible (true); / / construct a new object using reflection Singleton obj1 = construct.newInstance (); / / get the singleton object Singleton obj2 = Singleton.getInstance () in the normal way; System.out.println (obj1 = = obj2) / / false}

Destruction method 2. Serialization and deserialization destroy singleton pattern

Public static void main (String [] args) {/ / create the output stream ObjectOutputStream oos = new ObjectOutputStream ("Singleton.file"); / / write the singleton object to the file oos.writeObject (Singleton.getInstance ()); / / read the singleton object File file = new File ("Singleton.file") from the file; ObjectInputStream ois = new ObjectInputStream (new FileInputStream (file)); Singleton newInstance = (Singleton) ois.readObject () / / determine whether it is the same object System.out.println (newInstance = = Singleton.getInstance ()); / / false}

The reason why the addresses of the two objects are not equal is that when the readObject () method reads the object, it must return a new object instance, which must point to the new memory address.

3. Enumeration class

Using enumerations to implement singleton patterns (tricks and enumerations) is also recommended in Effective Java to instantiate on a case-by-case basis. At the time of initialization, we already know the types of several actual classes. Its benefits: more concise, pro bono serialization mechanism that absolutely prevents multiple instantiations, even in the face of complex sequence and reflection attacks.

Public enum SingletionEnum {SingletionEnum ("enumeration of singletons"); private String str; private SingletionEnum (String str) {this.setStr (str);} public String getStr () {return str;} public void setStr (String str) {this.str = str } = / / what is enum? Itself is also a Class class public enum EnumSingle {INSTANCE; public EnumSingle getInstance () {return INSTANCE;}}

It does not need to do any additional operations to ensure object singularity and thread safety.

When we want to break the singleton pattern through reflection, we report an error directly:

/ / what is enum? It is also a Class class public enum EnumSingle {INSTANCE; public EnumSingle getInstance () {return INSTANCE;}} class Test {public static void main (String [] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {EnumSingle instance1 = EnumSingle.INSTANCE; / / get Constructor declaredConstructor = EnumSingle.class.getDeclaredConstructor (String.class,int.class); declaredConstructor.setAccessible (true) EnumSingle instance2 = declaredConstructor.newInstance (); / / NoSuchMethodException: com.kuang.single.EnumSingle. () System.out.println (instance1); System.out.println (instance2);}}

Prevent reflection: the enumerated class inherits the Enum class by default, and when newInstance () is called with reflection, it determines whether the class is an enumerated class, and if so, throws an exception.

Prevent deserialization: when reading singleton objects, each enumerated type and enumerated name are unique, so when serializing, only the enumerated type and variable name are output to the file, when the read-in file is deserialized into an object, use the valueOf (String name) method of the Enum class to find the corresponding enumerated object according to the variable name. There are only a few cases in which enumerated types restrict the master class. So, in the process of serialization and deserialization, only enumerated types and names are written out and read, and there is no operation on the object.

This is the end of the content of "how to implement the Java singleton pattern". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report