On the JAVA platform, the roles that implement asynchronous calls have the following three roles: the caller's real data in the bill of lading
When a caller calls time-consuming operation and cannot return data immediately, he will first return a bill of lading. Then, after a break, the real data will be obtained by using the bill of lading.
Go to the cake shop to buy cakes, you don’t need to wait for the cake to be made (assuming it takes a long time to make it), you just need to get a bill of lading (go to do something else). When the cake is ready, you can get the bill of lading The cake is OK.
public class Main { public static void main(String[] args) { System.out.println("main BEGIN"); Host host = new Host(); Data data1 = host.request(10, 'A') ; Data data2 = host.request(20, 'B'); Data data3 = host.request(30, 'C'); System.out.println("main otherJob BEGIN"); try { Thread.sleep(200); } catch (InterruptedException e) { } System.out.println("main otherJob END"); System.out.println("data1 = " + data1.getContent()); System.out.printl n("data2 = " + data2 .getContent()); System.out.println("data3 = " + data3.getContent()); System.out.println("main END"); } }
The main class here is equivalent to "customer", and the host is equivalent to "cake shop". Customers ordering cakes from "cake shop" is equivalent to "submit request request". The returned data data is an instance of FutureData, which is equivalent to picking up the goods. Single, not the real "cake". After a period of time (after sleeping for a period of time), call data1.getContent(), which means obtaining the bill of lading to obtain the execution result.
Let’s take a look at what the cake shop did after the customer ordered the cake:
public class Host { public Data request(final int count, final char c) { System.out.println("request(" + count + ", " + c + ") BEGIN"); // (1) Create FutureData Of Entity final FutureData future = new FutureData(); // (2) In order to establish the RealData entity, start a new thread new Thread() { public void run() { //Use count, future, and c in an anonymous inner class. RealData realdata = new RealData(count, c); future.setRealData(realdata); } }.start(); System.out.println("request(" + count + ", " + c + ") END" ); // (3) Retrieve the FutureData entity as the return value return future; } }
After receiving the request, the host ("cake shop") became an instance future of "book of lading" FutureData, and then ordered the "cake maker" RealData to make the cake. Realdata is equivalent to starting a thread to make the cake. Then what the host returns to the customer is just the "book of lading" future, not the cake. After the cake is finished, the cake maker can give the corresponding "book of lading" cake, that is, future.setRealData(realdata).
Let’s take a look at how the cake maker makes cakes:
Create a string containing count c characters. It takes some time to show that the violation is illegal, and sleep is used.
public class RealData implements Data { private final String content; public RealData(int count, char c) { System.out.println("making RealData(" + count + ", " + c + ") BEGIN"); char[] buffer = new char[count]; for (int i = 0; i < count; i++) { buffer[i] = c; try { Thread.sleep(1000); } catch (InterruptedException e) { } } System. out .println("making RealData(" + count + ", " + c + ") END"); this.content = new String(buffer); } public String getContent() { return content; } }
Now let’s take a look at how the “bill of lading” future corresponds to the “content” of the cake:
public class FutureData implements Data { private RealData realdata = null; private boolean ready = false; public synchronized void setRealData(RealData realdata) { if (ready) { return; // Prevent setRealData from being called more than twice. } this.realdata = realdata; this.ready = true; notifyAll(); } public synchronized String getContent() { while (!ready) { try { wait(); } catch ( InterruptedException e) { } } return realdata.getContent (); } }
After the customer finishes his own business, he will take his own "book of lading" to pick up the cake:
System.out.println("data1 = " + data1.getContent());
If the cake is not ready, you have to wait:
while (!ready) { try { wait(); } catch (InterruptedException e) { } //Only return realdata.getContent() can be obtained after it is done;
Program Analysis
For each request, host will generate a thread, which is responsible for generating the "cake" needed by the customer. After waiting for a while, if the cake is not ready, customers must wait. The customer can only take away the cake until the "cake is made", that is, future.setRealData(realdata); is executed.
Each thread is just responsible for making the "cake" that a specific customer needs. That is, customer A corresponds to cake master A, and customer B corresponds to cake master B. Even if Customer B’s cake is prepared first, Customer A can only wait for the cake master A to prepare the cake. In other words, there is no competitive relationship between customers.
Two methods of FutureData are set to synchronized. In fact, the mutually exclusive relationship between cake master A and customer A, that is, customer A must wait for cake master A to prepare the cake before taking it away, and cake master B It doesn't matter whether the cake is ready.
This is all over this article. The code is simple. I hope it will be helpful for everyone to learn Java multi-threaded implementation of asynchronous calls. Thank you.