For example here:

public class Singleton{ private static Cat cat = new Cat(); public static Cat getInstance(){ return cat; } } 

Why is this option worse (if worse) than using the non-static getInstance () method?

PS The purpose of the question is to find out if there is a difference between using the static method getInstance () and non-static, in a situation where many threads can access it at the same time.

    3 answers 3

    The given variant is better than the variant with nonstatic getInstance because there is no other way. If the method is non-static, then you have to create a class Singleton every time. In addition, it is obvious that you implemented the singleton incorrectly. It turns out that you can get an instance of the class Cat through Singleton, or you can simply create as many new things via new Cat, which will be wrong and you can’t be protected from it. Therefore it is necessary to do

     public class Cat { private static final Cat cat = new Cat(); public static Cat getInstance(){ return cat; } } 

    From a multithreading point of view, there is no difference between the static and non-static method, if it is not marked as synchronized.

    The above option, as already mentioned, has a drawback: creating an instance when a class is loaded (often at the start of an application). To avoid this problem, you can use the Initialization on Demand Holder idiom pattern.

     public class Cat{ private Cat() { } private static class LazyHolder { private static final Cat INSTANCE = new Cat(); } public static final Cat getInstance() { return LazyHolder.INSTANCE; } } 

    In this situation, an effective thread safety is achieved and a lazy initialization is obtained (lazy-load singleton).

    However, in most cases there is no need to make such a complex structure, and it is enough to implement the first method.

    • It seems to me that it is still necessary to make the designer private. - Nick Volynkin

    I see the discussion here has come down to a discussion of the singleton pattern :)

    Actually, if you answer the question " How does a static method behave in a multithreaded application? " You need to know the following:

    1) From the static method, only static fields and methods are available, so problems can arise only with them (or else with the parameters and objects passed to the method, stored in local variables, but this does not depend on the use of static), or more precisely, with entries in static fields. In the above example, the entry in such a field occurs only once - when the class is loaded.

    2) Using the synchronized static method is absolutely equivalent to using a class object as a mutex. The following two methods work identically:

     class Example{ static void foo(){ synchronized(Example.class){ //method body } } synchronized static void bar(){ //method body } } 

    3) Without using synchronized in a method or with a method, calling its code is no different in terms of multithreading from calling an ordinary method.

    Finally, I will propose another way to implement the singleton pattern, which in my opinion is very elegant and effective - no problems with initialization / multithreading.

     enum Singleton{ Instance; //methods } 

      The getInstance method in the implementation of the Singleton pattern can only be static. Because this is the main idea of ​​the pattern: the object should be only one and should be accessible from any class of our application. In this implementation of the pattern, there will be no problems with multithreading, because the modification operation here is only new Cat (), which will be called only once. Another question is that such a pattern implementation is good only if

      1. You are absolutely sure that there can be no exceptions in the constructor
      2. It does not matter to you that initialization occurs when the application is started, and not at the time of the first access.

      Indeed, many singletones have an empty or simple and fast-performing constructor. Then these two points can be ignored. But sometimes the developer is still interested in lazy loading and checking for exceptions. Problems arise when the getInstance method looks like this:

       public static Cat getInstance(){ if (cat == null) cat = new Cat(); return cat; } 

      There really will be problems with multithreading. Therefore, for any non-atomic operations, you should use the synchronized modifier. Otherwise, we cannot guarantee that the Cat object is created only once. If there is a desire to deal well with multithreading in Java, I advise you to read the Java Concurrency and the manual on the Oracle website.

      • Why, the getInstance () method can only be static, let me disagree. What prevents us from writing: <code> Cat tom = new Singleton (). GetInstance () </ code> I’m probably coming from a distance, the purpose of my question is to find out if there is a difference between using the static getInstance () method and non-static method when it can be accessed by many threads at the same time. I have a suspicion that this is not a matter of taste. - elk
      • Indeed, there is a wrapper. Are synchronized / volatile used in your two examples? Cat - with changeable fields, setters? Non-static methods are heaped, and have their own copy of the context. Static is called directly. What is interesting, there may be differences. Maybe this is due to the fact that volatile began to work well only with Java 1.5. Or the author might need the ability to override the getInstance method. - Nicolas Chabanovsky
      • "What prevents us from writing: Cat tom = new Singleton (). GetInstance ()" - this is complete madness so to do. Then why do we need it at all if everyone can do new Singleton wherever he wants? Look at last, at first, how singltons are made, and only then think about multithreading. And no synchronized / volatile is needed here. - cy6erGn0m
      • "Therefore, for any non-atomic operations it is worth using the synchronized modifier" - not always true - cy6erGn0m
      • This is not a single Myers. Here I called the container container Singleton, and the class whose object we get is Cat is not accidental, the expression "new Singleton ()" will not return us a new object of type Cat, I took the singleton as an example (perhaps not very successfully). If you check in one thread, then static getInstance () is faster than non-static, indeed, it takes time to create a new (even simple) Singleton object, but in many ways it’s impossible to compare them. If the static method getInstance () is accessed by 200 threads at the same time will not affect whether its static nature will affect performance - elk