Java multi-line thread-safe single case mode _java

Source: Internet
Author: User
Tags static class thread class

Concept:
The single case pattern in Java is a common design pattern, the single example mode is divided into three kinds: the lazy type single case, the A Hungry man type single case, the registration type single example three kinds.
A single case pattern has some features:
1, Singleton class can only have one instance.
2. A singleton class must create its own unique instance.
3. A singleton class must provide this instance to all other objects.
The singleton pattern ensures that a class has only one instance and instantiates it itself and supplies the instance to the entire system. In computer systems, the driver objects of thread pools, caches, log objects, dialog boxes, printers, and graphics cards are often designed as single examples. These applications have more or less the functionality of the resource manager. Each computer can have several printers, but only one printer Spooler to prevent two print jobs from being exported to the printer at the same time. Each computer can have several communication ports, and the system should centrally manage these communication ports to avoid a single communication port being invoked simultaneously by two requests. In short, the choice of single case mode is to avoid inconsistent state, to avoid the administration of the Bulls.

Here are two main details: lazy type and a hungry man style

First, immediately loaded/a hungry man type

Before the method is invoked, the instance is created, and the code:

Package com.weishiyao.learn.day8.singleton.ep1;

public class MyObject {
  //immediate load mode = = Evil Han mode
  private static MyObject MyObject = new MyObject ()

  ; Private MyObject () {
  } public
  
  static MyObject getinstance () {
    //This code version for immediate loading
    ////This version of the code has the disadvantage that there cannot be other instance variables
    //Because the getinstance () method is not synchronized
    //So it is possible to have a thread-safe problem return
    MyObject
  }
}

Creating a Thread class

Package com.weishiyao.learn.day8.singleton.ep1;

public class Mythread extends Thread {
  @Override public
  void Run () {
    System.out.println ( Myobject.getinstance (). Hashcode ());
  }


To create a running class

Package com.weishiyao.learn.day8.singleton.ep1;

public class Run {public
  static void Main (string[] args) {
    mythread t1 = new Mythread ();
    Mythread t2 = new Mythread ();
    mythread t3 = new Mythread ();
    T1.start ();
    T2.start ();
    T3.start ();
  }


Run results
167772895
167772895
167772895
Hashcode is the same value, indicating that the object is also the same, which shows that the simple mode is implemented immediately loaded

Second, delayed loading/lazy type

The instance is created after the method is called, and the implementation can put the instantiation into an parameterless constructor so that an instance of the object is created only when the call is made, and the code:

Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP2;

public class MyObject {
  private static MyObject MyObject;
  
  Private MyObject () {
    
  } public
  
  static MyObject getinstance () {
    //deferred load
    if (MyObject!= null) {
      
    } else {
      myObject = new MyObject ();
    }
    Return MyObject
  }
}

Creating a Thread class

Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP2;

public class Mythread extends Thread {
  @Override public
  void Run () {
    System.out.println ( Myobject.getinstance (). Hashcode ());
  }


To create a running class

Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP2;

public class Run {public
  static void Main (string[] args) {
    mythread t1 = new Mythread ();
    T1.start ();
  }


Run results

167772895

This way, although an instance of an object is taken out, if multiple instances are present in a multithreaded environment, this is not a singleton pattern.

Run the test class

Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP2;

public class Run {public
  static void Main (string[] args) {
    mythread t1 = new Mythread ();
    Mythread t2 = new Mythread ();
    mythread t3 = new Mythread ();
    mythread T4 = new Mythread ();
    Mythread T5 = new Mythread ();
    T1.start ();
    T2.start ();
    T3.start ();
    T4.start ();
    T5.start ();
  }


Run results

980258163
1224717057
1851889404
188820504
1672864109
Since there is a problem, it is necessary to solve the problem in the lazy mode of multithreaded solution, code:

The first scheme, the most common, adds synchronized, and synchronized can be added to different locations

The first method of locking

Package com.weishiyao.learn.day8.singleton.ep3;

public class MyObject {
  private static MyObject MyObject;
  
  Private MyObject () {
    
  }
  
  synchronized public static MyObject getinstance () {
    //lazy load
    try {
      if ( MyObject!= null) {
        
      } else {
        //simulate doing some preparatory work before creating the object
        Thread.Sleep (watts);
        MyObject = new MyObject ();
      }
      
    } catch (Interruptedexception e) {
      e.printstacktrace ();
    }
    Return MyObject
  }
}

This synchronized synchronization scheme leads to inefficiencies, and the entire approach is locked.

The second type of synchronized use scheme

Package com.weishiyao.learn.day8.singleton.ep3;

public class MyObject {
  private static MyObject MyObject;
  
  Private MyObject () {
    
  } public
  
  static MyObject getinstance () {
    //lazy load
    try {
      synchronized ( Myobject.class) {
        if (MyObject!= null) {
          
        } else {
          //simulate doing some preparatory work before creating the object
          Thread.Sleep (watts);
          MyObject = new MyObject ();}}
      
      
    catch (Interruptedexception e) {
      e.printstacktrace ();
    }
    Return MyObject
  }
}

This approach is as inefficient as all the code within the method is locked, just to lock in the key code, and the third synchronized use scenario
Package com.weishiyao.learn.day8.singleton.ep3;

public class MyObject {
  private static MyObject MyObject;
  
  Private MyObject () {
    
  } public
  
  static MyObject getinstance () {
    //deferred load
    try {
        if (MyObject!= null) {
   } else {
          //simulate doing some preparatory work before creating an object
          Thread.Sleep;
          Synchronized (myobject.class) {
            MyObject = new MyObject ();
          }
      
      
    catch (interruptedexception e) { C16/>e.printstacktrace ();
    }
    Return MyObject
  }
}

So it seems like the best solution, but, run the results, found that it is not thread-safe

Results:

1224717057
971173439
1851889404
1224717057
1672864109
Why?

Although the statement created by the object is locked, only one thread can complete the creation at a time, but when the first thread comes in to create the completion object, the second thread comes in and can continue to be created, because we lock the creation statement tightly, and the problem solution

Package com.weishiyao.learn.day8.singleton.ep3;

public class MyObject {
  private static MyObject MyObject;
  
  Private MyObject () {
    
  } public
  
  static MyObject getinstance () {
    //deferred load
    try {
        if (MyObject!= null) {
   } else {
          //simulate doing some preparatory work before creating an object
          Thread.Sleep;
          Synchronized (myobject.class) {
            if (MyObject = null) {
              MyObject = new MyObject ();
            }
      }}
      
      
    catch (Interruptedexception e) {
      e.printstacktrace ();
    }
    Return MyObject
  }
}

Only need to add a judge in the lock, you can guarantee a single case, this is DCL double check mechanism

The results are as follows:

1224717057
1224717057
1224717057
1224717057
1224717057
third, the use of built-in static class implementation of a single case

Main code

Package com.weishiyao.learn.day8.singleton.ep4;

public class MyObject {
  //inner class way
  private static class Myobjecthandler {
    private static MyObject MyObject = new MyObject ();
  }

  Public MyObject () {
  } public
  
  static MyObject getinstance () {return
    myobjecthandler.myobject;
  }
}

Thread Class Code

Package com.weishiyao.learn.day8.singleton.ep4;

public class Mythread extends Thread {
  @Override public
  void Run () {
    System.out.println ( Myobject.getinstance (). Hashcode ());
  }


Run class

Package com.weishiyao.learn.day8.singleton.ep4;

public class Run {public
  static void Main (string[] args) {
    mythread t1 = new Mythread ();
    Mythread t2 = new Mythread ();
    mythread t3 = new Mythread ();
    mythread T4 = new Mythread ();
    Mythread T5 = new Mythread ();
    T1.start ();
    T2.start ();
    T3.start ();
    T4.start ();
    T5.start ();
  }


Results

1851889404
1851889404
1851889404
1851889404
1851889404
A single case pattern of thread safety is obtained through the internal static class

Iv. serialization and deserialization of single case patterns

Built-in static classes can achieve thread-safe problems, but if you encounter a serialized object, the result of using the default method is more or more

MyObject Code

Package com.weishiyao.learn.day8.singleton.ep5;

Import java.io.Serializable;

public class MyObject implements Serializable {
  
  /**
   * */
  private static final long Serialversionuid = 888 L;

  Internal class way
  private static class Myobjecthandler {
    private static MyObject MyObject = new MyObject ();
  }

  Public MyObject () {
  } public
  
  static MyObject getinstance () {return
    myobjecthandler.myobject;
  }  protected MyObject readresolve () {
//    System.out.println () called Readresolve Method! ");
return    Myobjecthandler.myobject;
//  }
}

Business class

Package com.weishiyao.learn.day8.singleton.ep5;
Import Java.io.File;
Import Java.io.FileInputStream;
Import java.io.FileNotFoundException;
Import Java.io.FileOutputStream;
Import java.io.IOException;
Import Java.io.ObjectInputStream;

Import Java.io.ObjectOutputStream; public class Saveandread {public static void main (string[] args) {try {MyObject MyObject = Myobject.getinst
      Ance ();
      FileOutputStream fosref = new FileOutputStream (New File ("MyObjectFile.txt"));
      ObjectOutputStream oosref = new ObjectOutputStream (FOSREF);
      Oosref.writeobject (MyObject);
      Oosref.close ();
      Fosref.close ();
    System.out.println (Myobject.hashcode ());
    catch (FileNotFoundException e) {e.printstacktrace ();
    catch (IOException e) {e.printstacktrace ();
    } FileInputStream Fisref;
      try {fisref = new FileInputStream (New File ("MyObjectFile.txt"));
      ObjectInputStream iosref = new ObjectInputStream (FISREF); MyObject MyObject = (MyObject) iosref.readobject ();
      Iosref.close ();
      Fisref.close ();
    System.out.println (Myobject.hashcode ());
    catch (FileNotFoundException e) {e.printstacktrace ();
    catch (IOException e) {e.printstacktrace ();
    catch (ClassNotFoundException e) {e.printstacktrace ();

 }
    
    
  }
}

Results

970928725
1099149023
Two different hashcode, proving not the same object, solution, add the following code

Protected MyObject Readresolve () {
    System.out.println () called the Readresolve Method! ");
    return myobjecthandler.myobject;
  }

Called at the time of deserialization, you can get the same object

System.out.println (Myobject.readresolve (). Hashcode ());
Results

1255301379
Called the Readresolve Method!
1255301379
Same hashcode, proved to have got the same object

The use of static code block implementation of a single case

The code in the static code block is executed when the class is used, so it is possible to apply the static code fast feature to implement the simple pattern.

MyObject class

Package com.weishiyao.learn.day8.singleton.ep6;

public class MyObject {
  private static MyObject instance = null;

  Private MyObject () {
    super ();
  }
  
  static {
    instance = new MyObject ();
  }
  
  public static MyObject getinstance () {return
    instance;
  }
}

Thread class

Package com.weishiyao.learn.day8.singleton.ep6;

public class Mythread extends Thread {
  @Override public
  void Run () {for
    (int i = 0; i < 5; i++) {
      System.out.println (Myobject.getinstance (). Hashcode ());}}}


Run class

Package com.weishiyao.learn.day8.singleton.ep6;

public class Run {public
  static void Main (string[] args) {
    mythread t1 = new Mythread ();
    Mythread t2 = new Mythread ();
    mythread t3 = new Mythread ();
    mythread T4 = new Mythread ();
    Mythread T5 = new Mythread ();
    T1.start ();
    T2.start ();
    T3.start ();
    T4.start ();
    T5.start ();
  }


Run Result:

1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
A single case pattern of thread safety is also successfully obtained by performing only one feature of the static code block

Vi. enumerating data types using enum to implement a single case pattern

enumeration enum and static code block features are similar, when using enumerations, the constructor is invoked automatically, or it can be used to implement a single case pattern

MyObject class

Package com.weishiyao.learn.day8.singleton.ep7;

Import java.sql.Connection;
Import Java.sql.DriverManager;
Import java.sql.SQLException;


public enum MyObject {
  connectionfactory;
  
  Private Connection Connection;
  
  Private MyObject () {
    try {
      System.out.println ("Call MyObject construct");
      String url = "Jdbc:mysql://172.16.221.19:3306/wechat_1?useunicode=true&characterencoding=utf-8";
      String name = "root";
      String password = "111111";
      String drivername = "Com.mysql.jdbc.Driver";
      Class.forName (drivername);
      Connection = drivermanager.getconnection (URL, name, password);
    } catch (ClassNotFoundException e) {
      e.printstacktrace ();
    } catch (SQLException e) {
      e.printstacktrace () ;
    }
  }
  
  Public Connection getconnection () {return
    Connection;
  }
}

Thread class

Package com.weishiyao.learn.day8.singleton.ep7;

public class Mythread extends Thread {
  @Override public
  void Run () {for
    (int i = 0; i < 5; i++) {
      Syst Em.out.println (MyObject.connectionFactory.getConnection (). Hashcode ());}}}


Run class

Package com.weishiyao.learn.day8.singleton.ep7;

public class Run {public
  static void Main (string[] args) {
    mythread t1 = new Mythread ();
    Mythread t2 = new Mythread ();
    mythread t3 = new Mythread ();
    mythread T4 = new Mythread ();
    Mythread T5 = new Mythread ();
    T1.start ();
    T2.start ();
    T3.start ();
    T4.start ();
    T5.start ();
  }


Run results

Called the construction of the MyObject
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
This type of writing exposes the enumeration class, violates the "principle of responsibility", and wraps the enumeration with a single class

Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP8;
Import java.sql.Connection;
Import Java.sql.DriverManager;


Import java.sql.SQLException;
    
    public class MyObject {public enum Myenumsingleton {connectionfactory;
    
    Private Connection Connection;
        Private Myenumsingleton () {try {System.out.println ("call MyObject construct");
        String url = "Jdbc:mysql://172.16.221.19:3306/wechat_1?useunicode=true&characterencoding=utf-8";
        String name = "Root";
        String password = "111111";
        String drivername = "Com.mysql.jdbc.Driver";
        Class.forName (drivername);
      Connection = drivermanager.getconnection (URL, name, password);
      catch (ClassNotFoundException e) {e.printstacktrace ();
      catch (SQLException e) {e.printstacktrace ();
    } public Connection getconnection () {return Connection; } public static Connection getconnection () {return Myenumsingleton.conneCtionfactory.getconnection ();

 }
}

Changing the thread code

Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP8;

public class Mythread extends Thread {
  @Override public
  void Run () {for
    (int i = 0; i < 5; i++) {
      Syst Em.out.println (Myobject.getconnection (). Hashcode ());}}}


Results
Called the construction of the MyObject
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121

The above summarizes the various situations and solutions that are encountered when the simple mode is combined with multithreading for later use.

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.