Analysis of selector mechanism of Java NiO class library — to
Since the version, a new class library has been released, which not only introduces a new and efficient mechanism, but also introduces the asynchronous mode of multiplexing. The package of mainly contains the following abstract data types:
When the class library was writing relevant network programs, he found some exceptions. The abnormal error information made him start to investigate. When Zhao Kun guessed and investigated some of the underlying mechanisms I shared, we thought it was a very interesting thing. Therefore, after a series of investigations with Zhao Kun, we found a lot of interesting things, which led to the emergence of this article. This is why the author of this article is signed by both of us.
For developers, this is not our strength. This article is essentially out of curiosity, because on the surface, it seems to have done something that surprises those of us.
Class library is super easy to cross platform. Except for some minor remarks on performance, programmers from previous backgrounds will never find it very difficult. Of course, for programs that have been used to using the operating system (system call) for a long time, they may be a little confused in the face of the "alternative" method of operating system resources, but everything changes. They only need to have a certain understanding of the object-oriented design pattern. In a short time, their class libraries can play as they like.
When designing related network programs, people from different backgrounds first think of the framework of multiplexing. When they think of multiplexing, they can immediately think of system calls. Therefore, when you see the classes in, you will feel more cordial. After a little reference to the manual and related routines, a multiplexing framework will be presented in a short time. It's no problem to do a unit test. Everything is as usual. Then tell the brothers that after the framework is completed, we will develop and unit test on the, and then integrate and test on the running environment. I thought to myself that cross platform is good. Development activities can cross platform.
The last unit test run began to have an exception. Looking at the function stack with an error in running the exception, the exception was thrown by and the error message was.
Why did you report an error? Shouldn't it? When there is no connection, how can you report this error?
Of course, your program will be very familiar with the call of the operating system. Although the system call made by your virtual machine has disappeared, your programmer must be much more sensitive than your program.
Old bird from. Sure enough, I opened the running process and found some links to connect myself. So another problem arises,
Why? Why do you have your own connection? I don't have my own connection in my program. How can I have such a link? And the port number of your own connection is actually some strange ports.
What are you doing? Do you want to create a link to connect yourself? Write a program to see:
Times, and then rest for seconds so that I can use the tool to view the process. There is no problem in compiling the program. When it runs, you can see the following dialog box: (there is actually a connection. We can know from the connection port that it is connected to each other, for example, the first is connected to the second, and the second is connected to the first)
Ah, not to mention whether this is a stupid thing. At least it is certain that we can catch up with some worms in consuming valuable system resources.
Change the value of to try, and soon you will find that your program has such an error: (about to run on my machine)
, but it just lets us understand what we are doing behind everyone's back. The above "stupid connections" are on the platform. If there is no accident, it should be similar.
Ran down. Using the command, you don't see yourself and your connection. Looks like you used a different mechanism from on?!
If you don't build your own connection to the server, the file descriptor and port will be saved. In other words, if we call one, there should be no exceptions.
About, not as good as)
So I thought of using the command to view the open file.
There are, files in total (of course, pipes are always paired), as shown in the figure below.
In this case, do not connect, but use pipes. It seems that this pipeline is also given to itself. Therefore, we can draw the following conclusions:
Next, I will establish two links with myself. It consumes not only two connections and ports, but also file descriptors.
I will build two pipelines myself and myself. The file descriptors of both systems are also consumed.
In this case, the reason why you choose to connect instead of is either because of performance problems or resource problems. Perhaps, the performance of the pipeline under is slower than that of the link, or the pipeline under may consume more resources than the link. The details of these implementations need to be excavated at a deeper level.
Mechanisms on different platforms.
Are you going to design it like this? If the old cannot be multiplexed, as shown in the figure below, open more threads to listen to each file descriptor one by one. If this is resource-consuming and inefficient. Then why do you still need to connect yourself in the new mechanism, and you still need to connect repeatedly, consuming double resources?
The search engine didn't find why. I only saw many people in the newspaper, but there was no explanation.
And the new in network programming. It looks really good and powerful. But it seems that this implementation will have some unnecessary overhead.
The framework of. After we read the source code of the framework. It is found that there is such a mechanism in:
The framework creates a thread for the object.
The method of the thread of the object will take out a pile from a queue, and then use the method to listen whether there is data that can be read and written.
The most important thing is that if there is a new join in the queue, it will be awakened and the latest collection will be restarted.
To wake up a method, just call the method.
For programmers, a thread blocked on can be awakened in the following three ways:
Write, or exception.
。
Signal. Can be issued by or.
To wake up blocked, you can only use these three methods, including:
The second method can be excluded because once blocked, it should not be possible to modify its time.
The third kind seems to be implemented only on, and there is no such signal notification mechanism on.
, you will establish a connection between yourself and yourself; A pair will be opened at the top (usually in pairs at the bottom). It is estimated that we can guess - that is, if you want to wake up, you only need to send data to your own connection point, so you can wake up the blocked thread.
We can easily prove this by issuing orders. See the figure below. In the figure, please pay attention to the following points:
String is to make a mark without getting lost in a large number of.
Blocked threads.
It is the system call of the method that is followed by the return of.
And the connections or built by yourself are used to realize the functions of and.
And signaling threads blocked on. However, signaling is not a cross platform standard (not all system calls support it), but all supported but not supported. Therefore, connection is used to realize this.
, I've been wondering whether the firewall settings will cause similar programs to execute abnormally? ha-ha. If you don't know such a mechanism, who knows how many programs will spend sleepless nights for the problems caused by this, especially programmers.
There are many other topics, such as how the compiler is, and whether it will do stupid things like the interpreter? I'll sell a key here. I'll talk about the compiler in another article. It will be released in the near future. Please look forward to it.