Java High concurrency Seven: concurrent Design model detailed _java

Source: Internet
Author: User
Tags static class stringbuffer

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.

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.