In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
The main content of this article is to explain the "Java I Pot O API performance example Analysis", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Now let the editor to take you to learn the "Java I Band O API performance example Analysis" it!
I. Overview
The scalability of IO API is of great significance to Web applications. In API prior to Java version 1.4, blocking iPot O disappointed many people. Starting with J2SE 1.4, Java finally has a scalable I _ J2SE O API. This paper analyzes and calculates the differences in scalability between new and old IO API. The write () method of the associated OutputStream must be called when Java writes data to Socket. The write () method call returns only when all the data is written. If the send buffer is full and the connection speed is slow, this call may take some time to complete. If the program uses only a single thread, other connections must wait, even if those connections are ready to call write (). To solve this problem, you have to associate each Socket with a thread; in this way, when one thread is blocked due to tasks related to Ibino, the other thread can still run.
Although threads are not as expensive as processes, considering the underlying operating platform, threads and processes belong to program structures that consume a lot of resources. Each thread takes up a certain amount of memory, and in addition, multiple threads also mean thread context switching, which also requires expensive resources. Therefore, Java needs a new API to separate the overly tight relationship between Socket and threads. In the new Java Iamp O API (java.nio.*), this goal has finally been achieved.
This paper analyzes and compares the simple Web servers written in the new and old I API O servers. Because HTTP, as a Web protocol, is no longer used for simple purposes as before, the examples presented here contain only key functions, that is, they neither consider security considerations nor strictly comply with protocol specifications.
2. HTTP server written in old API
First let's take a look at the HTTP server written in old-fashioned API. This implementation uses only one class. The main () method first creates a ServerSocket bound to port 8080:
Public static void main () throws IOException {
ServerSocket serverSocket = new ServerSocket (8080)
For (int iTuno; I < Integer.parseInt (args [0]); iTunes +) {
New Httpd (serverSocket)
}
}
Next, the main () method creates a series of Httpd objects and initializes them with the shared ServerSocket. In the constructor of Httpd, we ensure that each instance has a meaningful name, set the default protocol, and then start the server by calling the start () method of its superclass Thread. This results in an asynchronous call to the run () method, while the run () method contains an infinite loop.
In the infinite loop of the run () method, the blocking accpet () method of ServerSocket is called. When the client connects to port 8080 of the server, the accept () method returns a Socket object. Each Socket is associated with an InputStream and an OutputStream, both of which are used in subsequent handleRequest () method calls. This method reads the client's request, checks and processes it, and then sends the appropriate response to the client. If the client's request is valid, the file requested by the client is returned through the sendFile () method; otherwise, the client will receive the corresponding error message (calling the sendError () method).
While (true) {
...
Socket = serverSocket.accept ()
...
HandleRequest ()
...
Socket.close ()
}
Now let's analyze this implementation. Can it accomplish the task well? The answer is basically yes. Of course, the request analysis process can be further optimized because StringTokenizer has a poor reputation for performance. But the program has at least turned off TCP latency (which is inappropriate for short connections) and set buffering for outgoing files. And more importantly, all thread operations are independent of each other. Which thread handles the new connection request is determined by the native (and therefore fast) accept () method. Except for the ServerSocket object, any other resources that may need to be synchronized are not shared among the threads. This solution is fast, but unfortunately it is not very scalable because, obviously, threads are a limited resource.
3. Non-blocking HTTP server
Let's take a look at another scheme that uses the new non-blocking Imax O API. The new scheme is a little more complex than the original one, and it requires the cooperation of various threads. It contains the following four classes:
? NIOHttpd
? Acceptor
? Connection
? ConnectionSelector
The main task of NIOHttpd is to start the server. Just like the previous Httpd, a server Socket is bound to port 8080. The main difference between the two is that the new version of the server uses java.nio.channels.ServerSocketChannel instead of ServerSocket. Before you can explicitly bind Socket to a port using the bind () method, you must open a pipe (Channel). The main () method then instantiates a ConnectionSelector and an Acceptor. In this way, each ConnectionSelector can be registered with an Acceptor; in addition, ServerSocketChannel is provided when instantiating the Acceptor.
Public static void main () throws IOException {
ServerSocketChannel ssc = ServerSocketChannel.open ()
Ssc.socket () .bind (new InetSocketAddress (8080))
ConnectionSelector cs = new ConnectionSelector ()
New Acceptor (ssc, cs)
}
To understand the interaction between the two threads, let's first take a closer look at Acceptor. The main task of Acceptor is to accept incoming connection requests and register them through ConnectionSelector. The constructor of Acceptor calls the superclass's start () method; the run () method contains the necessary infinite loops. In this loop, an obstructive accept () method is called, which will eventually return a Socket object. This process is almost the same as that of Httpd, but instead of ServerSocket's accept () method, ServerSocketChannel's accept () method is used here. Finally, create a Connection object with the socketChannel object obtained by calling the accept () method as a parameter, and register it through the queue () method of ConnectionSelector.
While (true) {
...
SocketChannel = serverSocketChannel.accept ()
ConnectionSelector.queue (new Connection (socketChannel))
...
}
All in all: Acceptor can only accept connection requests and register connections through ConnectionSelector in an infinite loop. Like Acceptor, ConnectionSelector is a thread. In the constructor, it constructs a queue and opens a java.nio.channels.Selector with the Selector.open () method. Selector is one of the most important parts of the entire server, enabling programs to register connections and get a list of connections that have been allowed to read and write.
After the constructor calls the start () method, the infinite loop in the run () method begins to execute. In this loop, the program calls the select () method of Selector. This method blocks until one of the registered connections is ready for the wakeup O operation, or until the wakeup () method of the Selector is called.
While (true) {
...
Int I = selector.select ()
RegisterQueuedConnections ()
...
/ / handle the connection.
}
When a ConnectionSelector thread executes select (), no Acceptor thread can register a connection with that Selector, because the corresponding method is a synchronous method, which is important to understand. So queues are used here, and acceptor threads join connections to the queue if necessary.
Public void queue (Connection connection) {
Synchronized (queue) {
Queue.add (connection)
}
Selector.wakeup ()
}
Immediately following the operation of queuing the connection, Acceptor calls the wakeup () method of Selector. This call causes the ConnectionSelector thread to continue execution and return from the blocking select () call. Because Selector is no longer blocked, ConnectionSelector is now able to register connections from the queue. In the registerQueuedConnections () method, the implementation process is as follows:
If (! queue.isEmpty ()) {
Synchronized (queue) {
While (! queue.isEmpty ()) {
Connection connection =
(Connection) queue.remove (queue.size ()-1)
Connection.register (selector)
}
}
}
At this point, I believe that you have a deeper understanding of the "Java I Pot O API performance instance Analysis". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.