Java Multithreading Application implementation method _java programming

Source: Internet
Author: User
Tags garbage collection inheritance sleep thread class ticket

Before the habit of writing notes, now slowly found in time to sum up is how important, hehe. Although only sophomore, but also near graduation, to refuel.
This article is mainly about Java multithreading, mainly driven by examples. Because of the multithreading of the books and articles have a lot of, so I am also embarrassed to say, hehe, you can go to reference some of those books. My article is mainly about some practical problems. At the same time, I will review the material later,. Oh, we have a lot of advice.
At the same time hope to make some more technical friends. Thank you.
--------------------------------------------------------------------------------------------------------------- -------------------------------------
Multithreading in Java
In Java in order to implement multithreading, there are two ways, one is to continue the thread class, the other is to implement the Runable interface.
For classes that inherit thread directly, the general code framework is:

Copy Code code as follows:

Class Name extends thread{
Method 1;
Method 2;
...
public void Run () {
Other code ...
}
Property 1;
Property 2;
...

}




Let's look at a simple example:


Copy Code code as follows:

/**
* @author Rollen-holt inherit the thread class, call the Run method directly
* */
Class Hello extends Thread {

public Hello () {

}

Public Hello (String name) {
THIS.name = name;
}

public void Run () {
for (int i = 0; i < 5; i++) {
SYSTEM.OUT.PRINTLN (name + "Run" + i);
}
}

public static void Main (string[] args) {
Hello h1=new Hello ("A");
Hello h2=new Hello ("B");
H1.run ();
H2.run ();
}

private String name;
}




"Run Results":


A run 0


A Run 1


A Run 2


A Run 3


A run 4


B Run 0


B Run 1


B Run 2


B Run 3


B Run 4


We will find that these are sequential executions, stating that our calling method is incorrect and that we should call the start () method.


When we modify the main function above to look like the following:


Copy Code code as follows:

public static void Main (string[] args) {
Hello h1=new Hello ("A");
Hello h2=new Hello ("B");
H1.start ();
H2.start ();
}



Then run the program, the output of the possible results are as follows:


A run 0


B Run 0


B Run 1


B Run 2


B Run 3


B Run 4


A Run 1


A Run 2


A Run 3


A run 4


Because of the need to use the CPU resources, so each operation results are basically different, hehe.


Note: While we are calling here the start () method, we actually call the body of the run () method.


So: Why can't we just call the run () method directly?


My understanding is that the operation of the thread requires the support of the local operating system.


If you look at the source code for the start, you will find that:


Copy Code code as follows:

Public synchronized void Start () {
/**
* This method isn't invoked for the main method thread or "system"
* Group Threads Created/set up by the VM. Any new functionality added
* To the, the future may have to also is added to the VM.
*
* A Zero status value corresponds to state "NEW".
*/
if (threadstatus!= 0 | | | This!= me)
throw new Illegalthreadstateexception ();
Group.add (this);
Start0 ();
if (Stopbeforestart) {
Stop0 (Throwablefromstop);
}
}
Private native void Start0 ();



Notice that I use the red bold statement, which means that the start0 () is invoked here. And this method uses the native keyword, which means a function that invokes the local operating system. Because the implementation of multithreading requires the support of the local operating system.


However, the Start method repeats the invocation, and a Java.lang.IllegalThreadStateException exception appears.





By implementing the Runnable interface:


The general framework is:


Copy Code code as follows:

Class name implements Runnable{
Method 1;
Method 2;
...
public void Run () {
Other code ...
}
Property 1;
Property 2;
...

}




Let's take a look at a small example:


Copy Code code as follows:

/**
* @author Rollen-holt Implement runnable interface
* */
Class Hello implements Runnable {

public Hello () {

}

Public Hello (String name) {
THIS.name = name;
}

public void Run () {
for (int i = 0; i < 5; i++) {
SYSTEM.OUT.PRINTLN (name + "Run" + i);
}
}

public static void Main (string[] args) {
Hello h1=new Hello ("Thread A");
Thread demo= new Thread (H1);
Hello h2=new Hello ("thread B");
Thread Demo1=new thread (H2);
Demo.start ();
Demo1.start ();
}

private String name;
}




"Possible run Results":


Thread A runs 0


Thread B runs 0


Thread B runs 1


Thread B runs 2


Thread B runs 3


Thread B runs 4


Thread A runs 1


Thread A runs 2


Thread A runs 3


Thread A runs 4

about choosing inheritance thread or implementing the Runnable interface?
In fact, thread is also implementing the Runnable interface:

Copy Code code as follows:

Class Thread implements Runnable {
...
public void Run () {
if (target!= null) {
Target.run ();
}
}
}



In fact, the Run method in thread calls the Run method of the Runnable interface. Do not know that we found no, thread and runnable have implemented the Run method, this mode of operation is actually the agent mode. On the agent model, I have written a small example of hehe, you can look at the interest of: http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144847.html


The difference between thread and runnable:


If a class inherits thread, it is not appropriate for resource sharing. However, if the Runable interface is implemented, it is easy to achieve resource sharing.


Copy Code code as follows:

/**
* @author Rollen-holt inherits the thread class and cannot be shared by resources
* */
Class Hello extends Thread {
public void Run () {
for (int i = 0; i < 7; i++) {
if (Count > 0) {
System.out.println ("count=" + count--);
}
}
}

public static void Main (string[] args) {
Hello h1 = new Hello ();
Hello h2 = new Hello ();
Hello h3 = new Hello ();
H1.start ();
H2.start ();
H3.start ();
}

private int count = 5;
}




"Run Results":


Count= 5


Count= 4


Count= 3


Count= 2


Count= 1


Count= 5


Count= 4


Count= 3


Count= 2


Count= 1


Count= 5


Count= 4


Count= 3


Count= 2


Count= 1


As you can imagine, if this is a ticket system, if count represents the number of tickets, it does not share the resources.


we switch to the Runnable interface:


Copy Code code as follows:

/**
* @author Rollen-holt inherits the thread class and cannot be shared by resources
* */
Class Hello implements Runnable {
public void Run () {
for (int i = 0; i < 7; i++) {
if (Count > 0) {
System.out.println ("count=" + count--);
}
}
}

public static void Main (string[] args) {
Hello he=new hello ();
New Thread (He). Start ();
}

private int count = 5;
}




"Run Results":


Count= 5


Count= 4


Count= 3


Count= 2


Count= 1

Summarize it:
The advantages of implementing the Runnable interface than inheriting the thread class are:
1): Suitable for multiple threads of the same program code to handle the same resource
2): You can avoid the limitations of single inheritance in Java
3): Increase the robustness of the program, code can be shared by multiple threads, code and data Independent.

Therefore, I suggest that you implement the interface of strength.

Copy Code code as follows:

/**
* @author Rollen-holt
* Get the name of the thread
* */
Class Hello implements Runnable {
public void Run () {
for (int i = 0; i < 3; i++) {
System.out.println (Thread.CurrentThread (). GetName ());
}
}

public static void Main (string[] args) {
Hello he = new Hello ();
New Thread (He, "A"). Start ();
New Thread (He, "B"). Start ();
New Thread (He). Start ();
}
}




"Run Results":


A


A


A





B





Thread-0


Thread-0


Thread-0


Description if we do not specify a name, the system automatically provides the name.


To remind you: the Main method is actually a thread. In Java, so the thread is started at the same time, as to when, which is the first execution, completely see who first get the CPU resources.

In Java, you start at least 2 threads per program run. One is the main thread and one is the garbage collection thread. Because every time you use a Java command to execute a class, you actually start a JVM, and each JVM practices a process that starts in the operating system.
To determine whether a thread is started

Copy Code code as follows:

/**
* @author Rollen-holt to determine whether the thread is started
* */
Class Hello implements Runnable {
public void Run () {
for (int i = 0; i < 3; i++) {
System.out.println (Thread.CurrentThread (). GetName ());
}
}

public static void Main (string[] args) {
Hello he = new Hello ();
Thread demo = new Thread (he);
System.out.println ("Before thread starts---" + demo.isalive ());
Demo.start ();
SYSTEM.OUT.PRINTLN ("---after thread startup" + demo.isalive ());
}
}




"Run Results"


Before the thread starts---"False


---after thread startup true


Thread-0


Thread-0


Thread-0


The main thread may also end before the child thread ends. And the child thread is unaffected and will not end because of the end of the main thread.

forced execution of threads:

Copy Code code as follows:

/**
* @author Rollen-holt Thread Enforcement
* */
Class Hello implements Runnable {
public void Run () {
for (int i = 0; i < 3; i++) {
System.out.println (Thread.CurrentThread (). GetName ());
}
}

public static void Main (string[] args) {
Hello he = new Hello ();
Thread demo = new Thread (He, "thread");
Demo.start ();
for (int i=0;i<50;++i) {
if (i>10) {
try{
Demo.join (); Enforce demo
}catch (Exception e) {
E.printstacktrace ();
}
}
System.out.println ("Main thread executes-->" +i);
}
}
}




"Results of Run":


Main thread Execution--&gt;0


Main thread Execution--&gt;1


Main thread Execution--&gt;2


Main thread Execution--&gt;3


Main thread Execution--&gt;4


Main thread Execution--&gt;5


Main thread Execution--&gt;6


Main thread Execution--&gt;7


Main thread Execution--&gt;8


Main thread Execution--&gt;9


Main thread Execution--&gt;10


Thread


Thread


Thread


Main thread Execution--&gt;11


Main thread Execution--&gt;12


Main thread Execution--&gt;13


...

Hibernate of Threads:

Copy Code code as follows:

/**
* @author Rollen-holt-thread hibernation
* */
Class Hello implements Runnable {
public void Run () {
for (int i = 0; i < 3; i++) {
try {
Thread.Sleep (2000);
catch (Exception e) {
E.printstacktrace ();
}
System.out.println (Thread.CurrentThread (). GetName () + i);
}
}

public static void Main (string[] args) {
Hello he = new Hello ();
Thread demo = new Thread (He, "thread");
Demo.start ();
}
}




"Run Result": (the result is output every 2s)


Thread 0


Thread 1


Thread 2

Interrupt for Thread:

Copy Code code as follows:

/**
* @author Interrupt for Rollen-holt thread
* */
Class Hello implements Runnable {
public void Run () {
System.out.println ("Execute Run Method");
try {
Thread.Sleep (10000);
SYSTEM.OUT.PRINTLN ("Thread completes hibernation");
catch (Exception e) {
System.out.println ("dormant Interrupted");
Return Return to the program's call place
}
SYSTEM.OUT.PRINTLN ("thread terminated normally");
}

public static void Main (string[] args) {
Hello he = new Hello ();
Thread demo = new Thread (He, "thread");
Demo.start ();
try{
Thread.Sleep (2000);
}catch (Exception e) {
E.printstacktrace ();
}
Demo.interrupt (); Interrupt thread after 2s
}
}




"Run Results":


Execute the Run method


The dormancy is interrupted.

In a Java program, as long as the front desk has a thread running, the entire Java program process will not be an hour, so you can set up a background thread, so that even if the Java process hours, the subsequent thread can still continue to run.

Copy Code code as follows:

/**
* @author Rollen-holt Background thread
* */
Class Hello implements Runnable {
public void Run () {
while (true) {
System.out.println (Thread.CurrentThread (). GetName () + "in operation");
}
}

public static void Main (string[] args) {
Hello he = new Hello ();
Thread demo = new Thread (He, "thread");
Demo.setdaemon (TRUE);
Demo.start ();
}
}




Although there is a dead loop, but the program can still be done. Because the thread operation in the dead loop has been set to run in the background.


Priority of Threads:


Copy Code code as follows:

/**
* @author The priority of the Rollen-holt thread
* */
Class Hello implements Runnable {
public void Run () {
for (int i=0;i<5;++i) {
System.out.println (Thread.CurrentThread (). GetName () + "Run" +i);
}
}

public static void Main (string[] args) {
Thread h1=new thread (new Hello (), "A");
Thread h2=new thread (new Hello (), "B");
Thread h3=new thread (new Hello (), "C");
H1.setpriority (8);
H2.setpriority (2);
H3.setpriority (6);
H1.start ();
H2.start ();
H3.start ();

}
}




"Run Results":


A run 0


A Run 1


A Run 2


A Run 3


A run 4


B Run 0


C Run 0


C Run 1


C Run 2


C Run 3


C Run 4


B Run 1


B Run 2


B Run 3


B Run 4


。 But ask the reader not to mistake the priority to execute first. Who first executes or depends on who goes first the CPU's resources,

In addition, the primary thread's priority is 5.
Threads of comity.
In a thread operation, you can also use the yield () method to temporarily give the operation of one thread to another thread for execution.

Copy Code code as follows:

/**
* @author The priority of the Rollen-holt thread
* */
Class Hello implements Runnable {
public void Run () {
for (int i=0;i<5;++i) {
System.out.println (Thread.CurrentThread (). GetName () + "Run" +i);
if (i==3) {
System.out.println ("comity of Threads");
Thread.CurrentThread (). yield ();
}
}
}

public static void Main (string[] args) {
Thread h1=new thread (new Hello (), "A");
Thread h2=new thread (new Hello (), "B");
H1.start ();
H2.start ();

}
}




A run 0


A Run 1


A Run 2


A Run 3


Comity of Threads


A run 4


B Run 0


B Run 1


B Run 2


B Run 3


Comity of Threads


B Run 4


Sync and Deadlock:
"Problem leads": for example, for the ticket system, there are the following code:

Copy Code code as follows:

/**
* @author Rollen-holt
* */
Class Hello implements Runnable {
public void Run () {
for (int i=0;i<10;++i) {
if (count>0) {
try{
Thread.Sleep (1000);
}catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println (count--);
}
}
}

public static void Main (string[] args) {
Hello he=new hello ();
Thread H1=new thread (he);
Thread H2=new thread (he);
Thread H3=new thread (he);
H1.start ();
H2.start ();
H3.start ();
}
private int count=5;
}




"Run Results":


5


4


3


2


1


0


-1


Here comes the 1, which is obviously wrong. , the number of votes should not be negative.


If you want to solve this problem, you need to use synchronization. Synchronization means that only one thread is running in a unified time period,


Other threads must wait for this thread to complete before proceeding.


"Resolve problems Using Thread synchronization"


With synchronization, you can use the synchronized code block and the synchronization method to do both.

"Sync code block":
Syntax format:
Synchronized (Sync object) {
Code that needs to be synchronized
}
However, the current object, this is generally used as the synchronization object.
For example, for the above question of buying tickets, as follows:

Copy Code code as follows:

/**
* @author Rollen-holt
* */
Class Hello implements Runnable {
public void Run () {
for (int i=0;i<10;++i) {
Synchronized (this) {
if (count>0) {
try{
Thread.Sleep (1000);
}catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println (count--);
}
}
}
}

public static void Main (string[] args) {
Hello he=new hello ();
Thread H1=new thread (he);
Thread H2=new thread (he);
Thread H3=new thread (he);
H1.start ();
H2.start ();
H3.start ();
}
private int count=5;
}




"Run Result": (output one result per second)


5


4


3


2


1


"Sync Method"


You can also use synchronization methods.


Syntax format returns type method name (argument list) for synchronized method {


Other code


}


Now, we use the synchronization method to solve the above problem.


Copy Code code as follows:

/**
* @author Rollen-holt
* */
Class Hello implements Runnable {
public void Run () {
for (int i = 0; i < ++i) {
Sale ();
}
}

Public synchronized void Sale () {
if (Count > 0) {
try {
Thread.Sleep (1000);
catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println (count--);
}
}

public static void Main (string[] args) {
Hello he = new Hello ();
Thread H1 = new Thread (he);
Thread H2 = new Thread (he);
Thread h3 = new Thread (he);
H1.start ();
H2.start ();
H3.start ();
}

private int count = 5;
}




"Run Result" (one output per second)


5


4


3


2


1


As a reminder, multiple threads need to synchronize when they share a resource, but too much synchronization can lead to deadlocks.


The classic producer and consumer issues are listed here.


"Producer and Consumer issues"


Take a look at the problematic code first.


Copy Code code as follows:



Class Info {

Public String GetName () {
return name;
}

public void SetName (String name) {
THIS.name = name;
}

public int getage () {
return age;
}

public void Setage (int age) {
This.age = age;
}

Private String name = "Rollen";
private int age = 20;
}

/**
* Producer
* */
Class Producer implements runnable{
Private Info Info=null;
Producer (Info info) {
This.info=info;
}

public void Run () {
Boolean flag=false;
for (int i=0;i<25;++i) {
if (flag) {
This.info.setName ("Rollen");
try{
Thread.Sleep (100);
}catch (Exception e) {
E.printstacktrace ();
}
This.info.setAge (20);
Flag=false;
}else{
This.info.setName ("Chunge");
try{
Thread.Sleep (100);
}catch (Exception e) {
E.printstacktrace ();
}
This.info.setAge (100);
Flag=true;
}
}
}
}
/**
* Consumer Category
* */
Class Consumer implements runnable{
Private Info Info=null;
Public Consumer (Info info) {
This.info=info;
}

public void Run () {
for (int i=0;i<25;++i) {
try{
Thread.Sleep (100);
}catch (Exception e) {
E.printstacktrace ();
}
System.out.println (This.info.getName () + "<---->" +this.info.getage ());
}
}
}

/**
* Test class
* */
Class hello{
public static void Main (string[] args) {
Info info=new info ();
Producer pro=new Producer (info);
Consumer con=new Consumer (info);
New Thread (PRO). Start ();
New Thread (Con). Start ();
}
}




"Run Results":


rollen&lt;----&gt;100


chunge&lt;----&GT;20


chunge&lt;----&gt;100


rollen&lt;----&gt;100


chunge&lt;----&GT;20


rollen&lt;----&gt;100


rollen&lt;----&gt;100


rollen&lt;----&gt;100


chunge&lt;----&GT;20


chunge&lt;----&GT;20


chunge&lt;----&GT;20


rollen&lt;----&gt;100


chunge&lt;----&GT;20


rollen&lt;----&gt;100


chunge&lt;----&GT;20


rollen&lt;----&gt;100


chunge&lt;----&GT;20


rollen&lt;----&gt;100


chunge&lt;----&GT;20


rollen&lt;----&gt;100


chunge&lt;----&GT;20


rollen&lt;----&gt;100


chunge&lt;----&GT;20


rollen&lt;----&gt;100


chunge&lt;----&GT;20


As you can see from the results, the name and age are not.

So how to solve it?
<!--[if!supportlists]-->1) <!--[endif]--> Join sync
<!--[if!supportlists]-->2) <!--[endif]--> Join wait and wake up
Let's take a look at how to join the sync.

Copy Code code as follows:



Class Info {

Public String GetName () {
return name;
}

public void SetName (String name) {
THIS.name = name;
}

public int getage () {
return age;
}

public void Setage (int age) {
This.age = age;
}

Public synchronized void Set (String name, int age) {
This.name=name;
try{
Thread.Sleep (100);
}catch (Exception e) {
E.printstacktrace ();
}
This.age=age;
}

Public synchronized void get () {
try{
Thread.Sleep (100);
}catch (Exception e) {
E.printstacktrace ();
}
System.out.println (This.getname () + "<===>" +this.getage ());
}
Private String name = "Rollen";
private int age = 20;
}

/**
* Producer
* */
Class Producer implements Runnable {
Private info info = null;

Producer (Info info) {
This.info = info;
}

public void Run () {
Boolean flag = false;
for (int i = 0; i < ++i) {
if (flag) {

This.info.set ("Rollen", 20);
Flag = false;
} else {
This.info.set ("Chunge", 100);
Flag = true;
}
}
}
}

/**
* Consumer Category
* */
Class Consumer implements Runnable {
Private info info = null;

Public Consumer (Info info) {
This.info = info;
}

public void Run () {
for (int i = 0; i < ++i) {
try {
Thread.Sleep (100);
catch (Exception e) {
E.printstacktrace ();
}
This.info.get ();
}
}
}

/**
* Test class
* */
Class Hello {
public static void Main (string[] args) {
Info info = new info ();
Producer Pro = new Producer (info);
Consumer con = new Consumer (info);
New Thread (PRO). Start ();
New Thread (Con). Start ();
}
}




"Run Results":


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


chunge&lt;===&gt;100


From the results of the operation, the problem of confusion is solved, and now it is rollen corresponding 20,chunge for 100


, but there is also the problem of duplicate-read, there must be repeated coverage of the problem. If you want to solve this problem, you need to use the object class to help,


, we can use the wait and wake operation.


To complete the above function, we only need to modify the Info class hunger, in which the tag bit, and by judging the flag bit to complete the wait and wake operation, the code is as follows:


Copy Code code as follows:



Class Info {

Public String GetName () {
return name;
}

public void SetName (String name) {
THIS.name = name;
}

public int getage () {
return age;
}

public void Setage (int age) {
This.age = age;
}

Public synchronized void Set (String name, int age) {
if (!flag) {
try{
Super.wait ();
}catch (Exception e) {
E.printstacktrace ();
}
}
This.name=name;
try{
Thread.Sleep (100);
}catch (Exception e) {
E.printstacktrace ();
}
This.age=age;
Flag=false;
Super.notify ();
}

Public synchronized void get () {
if (flag) {
try{
Super.wait ();
}catch (Exception e) {
E.printstacktrace ();
}
}

try{
Thread.Sleep (100);
}catch (Exception e) {
E.printstacktrace ();
}
System.out.println (This.getname () + "<===>" +this.getage ());
Flag=true;
Super.notify ();
}
Private String name = "Rollen";
private int age = 20;
Private Boolean flag=false;
}

/**
* Producer
* */
Class Producer implements Runnable {
Private info info = null;

Producer (Info info) {
This.info = info;
}

public void Run () {
Boolean flag = false;
for (int i = 0; i < ++i) {
if (flag) {

This.info.set ("Rollen", 20);
Flag = false;
} else {
This.info.set ("Chunge", 100);
Flag = true;
}
}
}
}

/**
* Consumer Category
* */
Class Consumer implements Runnable {
Private info info = null;

Public Consumer (Info info) {
This.info = info;
}

public void Run () {
for (int i = 0; i < ++i) {
try {
Thread.Sleep (100);
catch (Exception e) {
E.printstacktrace ();
}
This.info.get ();
}
}
}

/**
* Test class
* */
Class Hello {
public static void Main (string[] args) {
Info info = new info ();
Producer Pro = new Producer (info);
Consumer con = new Consumer (info);
New Thread (PRO). Start ();
New Thread (Con). Start ();
}
}




"Program Run Results":


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


chunge&lt;===&gt;100


Rollen&lt;===&gt;20


Look at the results first, you can know that the previous problem completely resolved.


Finish


PS (written in the back):


I know that the study is too bad, so I hope you can be a lot of guidance. In addition, there is a lot of knowledge about multithreading, because at present I also know not too much, wrote a number of commonly used. Although in the operating system of this course to learn a lot of threads and processes, such as the banker algorithm, and so on, there is time to add, we have any good information can leave a message, we share together, thank you.


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.