Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to master responsive programming and get started with Reactor

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

How to master responsive programming and start Reactor, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain for you in detail, people with this need can come to learn, I hope you can gain something.

Synchronous blocking

"do you know what synchronous blocking is?" of course I do. "what do you think of it?" this.

In a world of synchronous blocking, data follows wherever the code executes. If the data is too slow to keep up, the code stops there waiting for the data to arrive, and then executes with the data.

It can be said that code execution and data go hand in hand, never give up. hold your hand and grow old together with you. It's always touching.

If you don't quite understand it, you can think of code execution as behavioral actions that are designed to obtain / manipulate data.

For example, add, the action here is to perform the addition, and the data is the addition and the added. The result of the operation is another data, that is, the sum of two numbers.

It's just that in this Jiffri, the data runs very fast, (the register of CPU, can't it be fast?), we are almost unaware of the process of performing actions waiting for data. What are we going to do? let's look at an example that can pull them apart.

Of course, it is the database query, there are both network Imax O and disk Imax O, which is bound to be slower.

Suppose my business is like this, the code first goes to the database to query a user, then changes the user's password, and then updates it back to the database, and finally the code returns success.

If the network speed and database are slow, this may be the case. The code performs an action to query the database, then waits and waits, and so on, and finally the database returns the user, and then the code quickly changes the password and performs an action to update the database. then wait and wait, the flowers bloom again, and the database finally answers, and the update is successful. Then the code returns success, and it's all executed.

So the biggest feature of synchronous blocking code is that it will block if the data is not in place when it is on the road with data.

Finally, a little sublimation:

The so-called synchronization is to wait for the fast and slow, and then move forward together, indicating the purpose.

The so-called blocking is to find a way to make the fast stagnate and wait for the slow to come, which means the means.

In a word, synchronization is the end and blocking is the means.

Asynchronous non-blocking

"do you know what asynchronous non-blocking is?" of course I do, but I don't know what to think of it. "Oh, congratulations on the rush to answer." .

We live in an asynchronous world, but we are the least asynchronous people.

When you go to a restaurant for dinner, the waiter writes down your menu and gives it to the kitchen to serve others.

After the meal is ready in the kitchen, inform the waiter by ringing the bell, and the waiter will deliver the meal to your position.

The waiter is the main (or Ishock O) thread and leaves the task to the worker thread of the kitchen. When the kitchen receives the task, it also remembers the waiter who sent the task, and then the kitchen goes to perform the task, and the waiter is also busy with something else.

After the kitchen finished the task, the waiter at that time was notified, and after receiving the notice, the waiter went to carry out the next contents, such as delivering the meal to the guest table.

This is a very common asynchronous scenario, because one party is not willing to wait for (or keep an eye on) the other party, but does not know when the other party will finish, so he can only hope to let himself know when the other party is done. and then do the follow-up work on your own.

This is what we often call an asynchronous callback (or notification).

The project manager finished the meeting in the morning, assigned tasks to everyone, and gave the test case code to everyone, saying that whoever finished running the test case would be fine. Then the meeting was over and each went to work.

When you are done at 5pm, you start to run the test cases and, luckily, pass all at once. Even if your task is done, then you can do what you want to do, such as watching the official account of "programming New Theory".

The project manager is the main (or Ipool O) thread, handing the task to each developer's worker thread, and giving each person a piece of logical code that tells them to execute the logical code after their task is completed.

After the developer completes the task, he then executes the logic code, and when the logic code is finished, it is over. There is no need to inform the project manager.

This is also a common asynchronous scenario in which one party assigns a task to the other, gives it a piece of logical code, and then goes its separate ways. In the days after that, you go your way, I cross my single-log bridge, the well water does not invade the river, and there is no contact between old age and death.

This logical code is usually passed in through a Runnable interface and executed when the task is completed, so let's call it "complete execution" for the time being.

So the most important feature of asynchronous non-blocking code is that I assign tasks to you, you reply to me when you're done, and we don't delay each other.

Finally, a little sublimation:

The so-called asynchronism means that you take yours, I take mine, and we all go forward, indicating a form of fact.

The so-called non-blocking is fast walking, slow walking, not staying for you for a moment, indicating that it is an intuitive phenomenon.

In a word, asynchronism is a form and non-blocking is a phenomenon.

Asynchronous non-blocking itself does not have any obvious noteworthy features, note that I am talking about it "itself". Because our whole world is running in asynchronous non-blocking mode.

Play with your cell phone when you go to the toilet, play with your phone while waiting for the car, play with your phone when you go to work, play with your phone when you eat, play with your phone when you get home, and play with your phone when you sleep. It was the same the next day. Ha ha. There is no time when a person is blocked.

There is no denying that the society we live in is very complex, mainly because communication, communication and coordination between people is sometimes not an easy task.

By the same token, asynchronous non-blocking "itself" is not difficult, the difficulty lies in how to achieve it. After all, it is not an easy task for a group of stupid threads who do not understand human words to communicate and coordinate with each other.

Responsive type

The so-called responsive is that the outside world has changed and you have to react. So responsive programming is built around change.

How to collect the original change, how to inform the relevant processors, how to react, the process of reacting is actually leading to new changes, how the new changes should be collected, and how to tell the next processor, and so on, until it all ends.

It can be said that the whole nature is responsive, because they all respond to changes in the outside world or to changes in themselves.

Let's talk about human beings first. They put on clothes when they are cold, eat when they are hungry and go to the hospital when they are ill. Relax when you see green, calm when you see blue, and get excited when you see red.

In addition, animals and plants, sunflowers are called phototaxis around the sun, and the roots of plants growing toward places with more water are called hydrotaxis. Pigeons can distinguish directions by magnetic fields, and whales and returnees can use magnetic fields to remember the way they have traveled.

So the responsive "itself" is a very simple model, you give me a change, I make a response.

Both animals and plants have a complete set of sensory organs that can sense changes in the outside world. At the same time, they also have a super-high IQ or a perfect biological system that can respond to this change. This is the result of tens of thousands or even tens of millions of years of evolution, determined by genes, so it looks natural.

Let's take a look at the responsiveness of the programming world, which are also two questions: one is how to know the changes in the outside world, and the other is how to respond to these changes.

The code is inanimate, so it can only be simple and rough. How to know the change, let someone else tell you. How to react, then execute a piece of logical code.

When someone tells you, it is tantamount to an asynchronous callback / notification, and the execution of this piece of logic code can be incoming from the outside or a method of your own.

Now you see, asynchronous non-blocking is responsive.

Finally, a little sublimation:

The so-called responsive is a concept, or a programming model, it is not a knowledge, nor a technology. But it needs to use a technology, that is to implement asynchronous non-blocking technology.

Reactor

In traditional coding, the logical processing code is written as a method, the required data is passed in by the method parameters, and the processed data is returned by the return value of the method.

During execution, the main method is used as the entry point, and these methods are executed in a certain order, and the data flows in and out of each method in turn. When all the methods are executed, the data is processed and finished.

The whole process takes the execution of the logical code as the main line, and the data is only a necessary participant, because the code has to deal with the data, and if the data is not in place, the code stops and waits for the data to arrive.

This is a typical synchronous blocking execution process, which is very simple, easy to understand, and easy to write code.

So far, what we have mentioned is a responsive theory, so how to achieve it, there is really no clue for a moment.

Responsive is asynchronous non-blocking, which should be relative to synchronous blocking. Then we might as well apply the response to synchronous blocking and see what valuable discoveries we can get.

Responsive focus on two points, change and reaction, and the change comes before the reaction. Synchronous blocking also focuses on two things, execution logic and data, and the execution logic comes first and the data comes last.

Then start building a correspondence. Because "reaction" is a series of actions, it should correspond to "execution logic". That "change" can only correspond to "data", in fact, this is right, "data" from unavailable to available, itself is a "change".

This correspondence is perfectly established, but the logical order is completely contradictory. The response is dominated by change, which is easy to understand. I haven't changed, and you don't have to react. Synchronous blocking is dominated by execution logic, which is understandable. My code is not executed, and I don't need data at all.

It can be seen that their corresponding relationship is very perfect, but the dominant order is completely opposite, which is a very valuable discovery.

Because we only need to reverse the synchronization blocking, which is to achieve the general direction of the response. This kind of reasoning seems to be correct, but is it true in practice? Well, here's the thing.

Now please change your mind with me. The original logic code execution as the main line, data as participants. Now take the data as the main line and the logical code execution as the participant. To put it more bluntly, it turned out that the data was transferred to the logical code, and now the logical code is transferred to the data.

One might ask, how does the logical code pass? Haha, Lambda expressions, functional programming.

Imagine a long pipe in which the water is flowing all the time.

If you want the water to turn orange, just make an opening in the pipe, add a device that can continuously put orange dye, and the water that flows through it turns orange.

If you want to sweeten the orange water, just make an opening in the back tube and install a device that can continuously put in white sugar, and as a result, the water flowing through it becomes sweet.

By the same token, you can continue to install a device for adding citric acid at the back to make the water sour, and then continue to install a device for pressing carbon dioxide at the back to allow the water to bring bubbles.

Finally, it was found that the tap water became Fanta after many processes.

If you think of the water flow as a data flow and the delivery device as a logic code, it becomes that the data flows into the first logic code first, then into the second logic code, and then flows down to the end.

This is the data as the main line, the logic code is only participants, and it is also the principle of Reactor to achieve responsive programming, Spring officially uses the responsive class library is Reactor.

Among them, the two functions of "data as the main line" and "notify the handler when a change" have been implemented in the Reactor library, and what we need to do is to "react to the change", that is, insert logic code.

Getting started with Reactor

In Reactor, there are two very important classes, Mono and Flux, which are data sources. Both of them have implemented the functions of "data as the main line" and "notify the handler when a change", and also provide a way for us to insert logical code to "react to the change".

Mono represents 0 or 1 data, and Flux represents 0 to more data. Let's start with simple Mono.

To design a simple example, first create a data source that contains only one data 10, the first processing is to add 1, the second processing is parity filtering, the third processing is to consume the data, and then it is over.

In order to clearly see what code the main thread is executing and which code the worker thread is executing, a lot of information is deliberately printed.

Public static void main (String [] args) {displayCurrTime (1); displayCurrThreadId (1); / / create a data source Mono.just (10) / / delay 5 seconds before transmitting data. DelayElement (Duration.ofSeconds (5)) / / perform a transformation on the data .map (n-> {displayCurrTime (2); displayCurrThreadId (2); displayValue (n); delaySeconds (2); return n + 1 }) / / perform a filter on the data. Filter (n-> {displayCurrTime (3); displayCurrThreadId (3); displayValue (n); delaySeconds (3); return n% 2 = = 0;}) / / if the data is gone, use the default value .defaultIfEmpty (9) / / subscribe a consumer to consume the data .subscribe (n-> {displayCurrTime (4); displayCurrThreadId (4); displayValue (n); delaySeconds (2) System.out.println (n + "consumed, worker Thread over, exit.");}); displayCurrTime (5); displayCurrThreadId (5); pause ();} / / display the current time static void displayCurrTime (int point) {System.out.println (point + ":" + LocalTime.now ());} / / display the current thread Id static void displayCurrThreadId (int point) {System.out.println (point + ":" + Thread.currentThread (). GetId () } / / display the current value static void displayValue (int n) {System.out.println ("input:" + n);} / / delay several seconds static void delaySeconds (int seconds) {try {TimeUnit.SECONDS.sleep (seconds);} catch (InterruptedException e) {e.printStackTrace ();}} / / main thread pauses static void pause () {try {System.out.println ("main Thread over, paused.") System.in.read ();} catch (IOException e) {e.printStackTrace ();}}

The following is the output:

1: 15:00:39.809 1: 15: 15:00:40.158 5: 1 main Thread over, paused. 2: 15:00:45.158 2: 9 input: 10 3: 15:00:47.160 3: 9 input: 11 4: 15:00:50.162 4: 9 input: 9 9 consumed, worker Thread over, exit.

You can see that the main thread finishes execution in less than 1 second. Then 5 seconds later the data is sent out from the data source to enter the first step of processing, 2 seconds later to enter the second step of processing, 3 seconds later to enter the third step of processing, the data is consumed, and it is over. Where the main thread Id is 1 and the worker thread Id is 9.

This code actually establishes a data channel, inserts processing logic at a specified location in the channel, and waits for the data to arrive.

The main thread executes the code that establishes the channel, and the main thread executes quickly, and the channel is built. At this time, it is just an empty channel, and there is no data at all.

When the data arrives, the worker thread executes the logical code of each node to process the data, and then passes the data to the next node, repeatedly until the end.

Therefore, when writing responsive code, be sure to keep in mind that what I do is to establish a data channel and insert the appropriate logic processing code at the specified location on the channel. At the same time, keep in mind that when the main thread finishes execution, only the channel is established and there is no data.

Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report