1. What is design pattern
In software engineering, design patterns are the solutions to the problems in software design which are ubiquitous (recurring). The term was introduced into computer science in the 1990 's by Erich Gamma (Erich Gamma) and others in the field of architectural design.
Famous 4 people: Erich gamma,richard Helm, Ralph Johnson, John vlissides (Gof)
"Design pattern: the foundation of reusable object-oriented Software" includes 23 modes
2. Single case mode
The class of a singleton object must guarantee that only one instance exists. Many times the entire system needs only one global object, which helps us coordinate the behavior of the system as a whole
For example: Global information configuration
The simplest implementation of a single example pattern:
public class Singleton {
private Singleton () {
System.out.println (' Singleton is create ');
}
private static Singleton instance = new Singleton ();
public static Singleton getinstance () {return
instance;
}
}
Uniqueness is determined by private constructor methods and static.
Disadvantages: When to produce an instance of bad control
Although we know that the first time a class singleton is loaded, an instance is produced.
But if there are other attributes in this class
public class Singleton {public
static int status=1;
Private Singleton () {
System.out.println ("Singleton is create");
}
private static Singleton instance = new Singleton ();
public static Singleton getinstance () {return
instance;
}
}
When using
System.out.println (Singleton.status);
This example is produced. Perhaps you do not want to produce this example at this time.
If the system is particularly concerned about this problem, the implementation of this single example is not very good.
The second way to solve the single case pattern:
public class Singleton {
private Singleton () {
System.out.println (' Singleton is create ');
}
private static Singleton instance = null;
public static synchronized Singleton getinstance () {
if (instance = = null)
instance = new Singleton ();
return instance
}
}
Allow instance to be created only when the getinstance () method is invoked, and to ensure thread safety by synchronized.
This controls when the instance is created.
This method is typical of deferred loading.
But there is a problem, in the context of high concurrency performance will have an impact, although only a judgment on return, but in the case of high concurrency, more or less will have a bit of impact, because they have to get synchronized lock.
For efficiency, there is a third way:
public class Staticsingleton {
private Staticsingleton () {
System.out.println (' Staticsingleton is create ');
}
private Static class Singletonholder {
private static Staticsingleton instance = new Staticsingleton ();
} Public
static Staticsingleton getinstance () {return
singletonholder.instance;
}
}
Because a class is loaded, its inner class is not loaded. This ensures that only the invocation of getinstance () will produce an instance, control the time of the generation of the instance, and implement deferred loading.
and remove the synchronized, make the performance more excellent, use static to ensure uniqueness.
3. Invariant mode
When the internal state of a class is created, it does not change throughout the life, it is the invariant class
Invariant mode does not require synchronization
To create a constant class:
Public final class Product {
//ensures no subclass
private Final String no;
A private property that is not fetched by another object to the
private final String name;
Final guaranteed attribute will not be assigned 2 times
private final double price;
Public Product (String No, string name, double) {
//The Data
super () must be specified when the object is created;
Cannot be modified since it was created
this.no = no;
this.name = name;
This.price = Price;
}
Public String Getno () {return
no;
}
Public String GetName () {return
name;
}
Public double GetPrice () {return price
}
}
Examples of immutable patterns in Java are:
Java.lang.String
Java.lang.Boolean
Java.lang.Byte
Java.lang.Character
Java.lang.Double
Java.lang.Float
Java.lang.Integer
Java.lang.Long
Java.lang.Short
4. Future mode
The core idea is to call asynchronously
Non-asynchronous:
Asynchronous:
The first Call_return returned an empty one because the task was not completed.
But this return is similar to the purchase order, in the future can be based on this order to get a result.
So this future model means that "the future" can be obtained by referring to the order or contract, and the "promise" will give the result in the future.
Simple implementation of future mode:
The caller gets a data, which may be a futuredata at first because the Realdata build is slow. At some time in the future, you can get realdata by Futuredata.
Code implementation:
Public interface Data {public String getresult (); The public class Futuredata implements Data {protected Realdata realdata = null;//futuredata is Realdata's wrapper protected boo
Lean IsReady = false;
Public synchronized void Setrealdata (Realdata realdata) {if (IsReady) {return;
} this.realdata = Realdata;
IsReady = true; Notifyall (); Realdata has been injected to notify GetResult ()} public synchronized String GetResult ()//Will wait for realdata construction to complete {while (!isready) {try {wait ();//Keep waiting until Realdata is injected} catch (Interruptedexception e) {}} return realdata.result;
Implemented by Realdata} public class Realdata implements Data {protected final String result;
The construction of the public realdata (String para) {//Realdata may be slow, requiring a long wait for the user, where the sleep simulation stringbuffer SB = new StringBuffer () is used.
for (int i = 0; i < i++) {sb.append (para);
try {///use sleep here instead of a very slow operating process thread.sleep (100);
catch (Interruptedexception e) {}} result = Sb.tostring (); Public String GetResult () {return reSult;
} public class Client {public Data request (final String querystr) {final futuredata future = new Futuredata ();
The build of New thread () {public void run () {//Realdata is slow,//So realdata realdata = new Realdata (QUERYSTR) in a separate thread;
Future.setrealdata (Realdata);
}}.start (); return future;
Futuredata will be returned immediately}} public static void Main (string[] args) {Client client = new Client ();
This will return immediately because the futuredata instead of the realdata data = client.request ("name") is obtained;
SYSTEM.OUT.PRINTLN ("complete request");
try {//Here you can replace the processing of other business logic with a sleep//in the process of dealing with these business logic, Realdata is created to make the most of the wait Time Thread.Sleep (2000);
catch (Interruptedexception e) {}//Use real data System.out.println ("data =" + Data.getresult ());
}
There is also support for multiple future modes in the JDK:
Next, use the classes and methods provided by the JDK to implement just the code:
Import java.util.concurrent.Callable;
public class Realdata implements callable<string> {
private String para;
Public realdata (String para) {
This.para = para;
}
@Override public
String call () throws Exception {
StringBuffer sb = new StringBuffer ();
for (int i = 0; i < i++) {
sb.append (para);
try {
thread.sleep;
} catch (Interruptedexception e) {
}
} return
sb.tostring ();
}
}
import java.util.concurrent.ExecutionException; import
Java.util.concurrent.ExecutorService;
Import java.util.concurrent.Executors;
Import Java.util.concurrent.FutureTask; public class Futuremain {public static void main (string[] args) throws Interruptedexception, executionexception {//Fabric
Futuretask futuretask<string> future = new Futuretask<string> (New Realdata ("a"));
Executorservice executor = executors.newfixedthreadpool (1);
The execution of Futuretask, equivalent to the Client.request ("a") in the previous example, sends a request//opens a thread here for Realdata call () execution Executor.submit (future);
SYSTEM.OUT.PRINTLN ("complete request");
try {//still can do additional data operations here, using sleep instead of other business logic processing Thread.Sleep (2000); catch (Interruptedexception e) {}///equivalent to Data.getresult (), get the return value of the call () method if the call () method does not finish executing, it will still wait for the SYSTEM.OUT.PR
INTLN ("data =" + Future.get ()); }
}
The note here is that Futuretask is a class with future functions and runnable functions. So it can run, and finally get.
Of course, if the real data is not ready when called to Future.get (), the blocking condition will still occur until the data is ready to be completed.
There are, of course, simpler ways:
Import java.util.concurrent.ExecutionException;
Import Java.util.concurrent.ExecutorService;
Import java.util.concurrent.Executors;
Import Java.util.concurrent.Future;
public class FutureMain2 {public
static void Main (string[] args) throws Interruptedexception,
executionexception {
Executorservice executor = executors.newfixedthreadpool (1);
Executes futuretask, equivalent to the Client.request ("a") in the previous example sending a request
//Opening a thread here to perform a realdata call () execution
future<string> Future = Executor.submit (New Realdata ("a"));
SYSTEM.OUT.PRINTLN ("complete Request");
try {
//still can do additional data operations here, using sleep instead of other business logic processing
thread.sleep;
} catch (Interruptedexception e) {
}
Equivalent to Data.getresult (), the return value of the call () method is obtained
//if the call () method is not completed at this time, it will still wait for the
System.out.println ("data =" + Future.get ());
}
}
Because the callable has a return value, you can return the future object directly.
5. Producer Consumers
Producer-consumer mode is a classic multithreaded design pattern. It provides a good solution for the collaboration between multithreading. In producer-consumer mode, there are typically two types of threads, that is, several producer threads and several consumer threads. The producer thread is responsible for submitting the user's request, and the consumer thread is responsible for handling the tasks submitted by the producer. The producer and the consumer communicate through a shared memory buffer.
There have been a number of ways to implement the producer consumer in Java, and there is no more elaboration here.