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 create a multithreaded server by Java

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

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

Most people do not understand the knowledge points of this article "Java how to create a multithreaded server", so the editor summarizes the following content, detailed content, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this "Java how to create a multithreaded server" article.

Looking back at how we created a multithreaded server MultiThreadRemoteFileServer, it depends on what happened a few days ago. To sum up, it is for each customer waiting for a connection new a thread to use, to allocate one. Whenever a client requests a connection, a new ConnectionHandler is created in a new Thread. This means that there may be a dozen Thread running throughout the system. Obviously, the overhead of the system will continue to increase as the number of connected customers increases. We can't help but consider the possibility that the system will be unbearable when the overhead increases to a certain extent. Therefore, we have to find a way to limit the number of connected customers and improve the efficiency of the server.

So the solution is: on the server side, we create a certain number of PooledConnectionHandler when the server starts, we put the incoming connections into a connection pool and let PooledConnectionHandler take care of the rest. The client program does not need to be modified at all, and the advantages of this design are as follows:

1. Limits the number of simultaneous connections allowed.

two。 You only need to start the PooledConnectionHandler thread a limited number of times.

The meaning of these two sentences will be reflected in subsequent programs, and the following is the structure of the PooledRemoteFileServer class:

Import Java.io.*

Import java.NET.*

Import java.util.*

Public class PooledRemoteFileServer {

Protected int maxConnections;// defines the maximum number of client connections that can be processed simultaneously protected int listenPort;// defines the port number to listen on

Protected ServerSocket serverSocket

Public PooledRemoteFileServer (int aListenPort, int maxConnections) {

ListenPort = aListenPort

This.maxConnections = maxConnections

}

Public static void main (String [] args) {

}

Public void setUpHandlers () {/ / create PooledConnectionHandler with the number of maxConnections

}

Public void acceptConnections () {/ / listens to incoming client connections on ServerSocket, exactly like the listener in the previous RemoteFileServer,MultiThreadRemoteFileServer

}

Protected void handleConnection (Socket incomingConnection) {

} / / connection handler

}

Again, let's first look at the main function.

Public static void main (String [] args) {

PooledRemoteFileServer server = new PooledRemoteFileServer (3000, 3)

Server.setUpHandlers (); / / unlike the main functions of all previous servers, we first need to create a connection pool in which there are three available connectionHandler

Server.acceptConnections (); / / once ready, start listening

Let's take a look at how to create three connectionHandler programs:

Public void setUpHandlers () {

For (int I = 0; I < maxConnections; iTunes +) {

PooledConnectionHandler currentHandler = new PooledConnectionHandler ()

New Thread (currentHandler, "Handler" + I) .start ()

}

}

The setUpHandlers () method creates maxConnections PooledConnectionHandler and activates them in the new Thread. PooledConnectionHandler is a thread body implemented with Runnable here. Creating Thread with objects that implement Runnable allows us to call start () on Thread and expect run () to be called on Runnable. That is, our PooledConnectionHandler will be waiting to process incoming connections, each in its own Thread. We only created three Thread in the example, and once the server is running, this cannot be changed.

Omit the acceptConnections () method here and take a look at the connection handler handleConnection (Socket incomingConnection)

Protected void handleConnection (Socket connectionToHandle) {

PooledConnectionHandler.processRequest (connectionToHandle)

}

Here, the connection handler directly calls the class method processRequest of the PooledConnectionHandler thread class to handle the listening connection. Obviously, this processRequest is a static method.

The methods in the PooledRemoteFileServer class all involve an important thread class, PooledConnectionHandler. Let's take a look at what such a class implemented with an interface looks like:

Public class PooledConnectionHandler implements Runnable {

Protected Socket connection;// represents the Socket currently being processed

Protected static List pool = new LinkedList (); / / A static LinkedList named pool holds the connections that need to be processed, that is, LinkedList is used to simulate a connection pool

Public PooledConnectionHandler () {/ / constructor

}

Public void handleConnection () {/ / A pair of connected iMago operations are here.

}

Public static void processRequest (Socket requestToHandle) {/ / handles customer connections and adds them to the connection pool

}

Public void run () {/ / wait for a connection to come. If it comes, call handleConnection () for processing.

}

}

As you can see, this class is very similar to ConnectionHandler on the day of multithreaded Socket, except that it has the means to deal with connection pooling.

First take a look at the processRequest () method to be used in the listener

Public static void processRequest (Socket requestToHandle) {

Synchronized (pool) {

Pool.add (pool.size (), requestToHandle)

Pool.notifyAll ()

}

}

The requestToHandle here is to deal with the customer connection socket. It can be said that what processRequest does is add customer connections to the connection pool. But to ensure that there is no other thread interference when operating on the connection pool (Pool), you need to acquire the object lock of the connection pool and use the synchronization block, and the previous concept of synchronized can come in handy here.

So, now that we are guaranteed to be the only wading people, we can add the incoming Socket to the end of the LinkedList. Once we have added a new connection, we can use pool.notifyall to notify other Thread waiting for the pool that the object lock of the connection pool is unlocked and is now available. On the other hand, it can also be said to notify another waiting thread that some conditions are already in place.

So what is the waiting thread?

Let's implement the run () method on PooledConnectionHandler, which will wait on the connection pool and process it as soon as there is a connection in the pool, so the thread that is going to process the connection is waiting:

Public void run () {

While (true) {

Synchronized (pool) {

While (pool.isEmpty ()) {

Try {

Pool.wait ()

} catch (InterruptedException e) {return;}

}

Connection = (Socket) pool.remove (0); / / grab the first connection in the pool and make it a connection to be processed soon

}

HandleConnection (); / / then hand it over to handleConnection for processing

}

}

This function tells us what each PooledConnectionHandler thread is mainly in the run. Obviously, it keeps looking to see if there are any connected connections in the connection pool, and if so, deal with it immediately, so it is waiting for the condition that the connection pool has a connection. So who's going to tell it that this condition has been met? it's obviously the processRequest. When processRequest sends a notification (pool.notify ()), this condition is satisfied, and the handler in run () no longer has to wait for a connection to be processed immediately. Conversely, until this condition is met, the thread on which wait () resides is still in a blocking state, or stagnant state. Since you also need to operate on pool, you also need to use synchronization blocks here.

Let's review the concept of object lock again. When run () has a pool mutex, how can processRequest () put the connection into the pool? The answer is that the call to wait () on the pool releases the lock, and wait () then grabs the lock again before returning itself. This allows other synchronization code of the pool object to acquire the lock.

Finally, let's look at the handleConnection () method in the PooledConnectionHandler thread. Unlike in a multithreaded server, our PooledConnectionHandler has a handleConnection () method. The code for this method is exactly the same as the code for the run () method on ConnectionHandler in a non-pooled, multithreaded server. First, we wrap OutputStream and InputStream in (using getOutputStream () and getInputStream () on Socket) BufferedReader and PrintWriter, respectively. Then we read the target file line by line, as we did in the multithreaded example. Once again, we take some bytes, put them in the local line variable, and write them out to the client. After completing the read and write operation, we close the FileReader and the open stream.

At this point, we can see that there are two classes in the program, PooledRemoteFileServer and PooledConnectionHandler.PooledRemoteFileServer do not directly deal with connection requests, it is only responsible for listening to these connections and throwing them into the connection pool, as for the specific aspects of processing, are left to PooledConnectionHandler.

Our server with connection pooling is finished. Let's review the steps for creating and using a "pool version" server:

1. Create a new kind of connection handler (we call it PooledConnectionHandler) to handle connections in the pool.

two。 Modify the server to create and use a set of PooledConnectionHandler.

Attached: the source code of PooledRemoteFileServer.java

Import java.io.*

Import java.net.*

Import java.util.*

Public class PooledRemoteFileServer {

Protected int maxConnections

Protected int listenPort

Protected ServerSocket serverSocket

Public PooledRemoteFileServer (int aListenPort, int maxConnections) {

ListenPort = aListenPort

This.maxConnections = maxConnections

}

Public void acceptConnections () {

Try {

ServerSocket server = new ServerSocket (listenPort, 5)

Socket incomingConnection = null

While (true) {

IncomingConnection = server.accept ()

HandleConnection (incomingConnection)

}

} catch (BindException e) {

System.out.println ("Unable to bind to port" + listenPort)

} catch (IOException e) {

System.out.println ("Unable to instantiate a ServerSocket on port:" + listenPort)

}

}

Protected void handleConnection (Socket connectionToHandle) {

PooledConnectionHandler.processRequest (connectionToHandle)

}

Public static void main (String [] args) {

PooledRemoteFileServer server = new PooledRemoteFileServer (3000, 3)

Server.setUpHandlers ()

Server.acceptConnections ()

}

Public void setUpHandlers () {

For (int I = 0; I < maxConnections; iTunes +) {

PooledConnectionHandler currentHandler = new PooledConnectionHandler ()

New Thread (currentHandler, "Handler" + I) .start ()

}

}

}

Class PooledConnectionHandler implements Runnable {

Protected Socket connection

Protected static List pool = new LinkedList ()

Public PooledConnectionHandler () {

}

Public void handleConnection () {

Try {

PrintWriter streamWriter = new PrintWriter (connection.getOutputStream ())

BufferedReader streamReader = new BufferedReader (new InputStreamReader (connection.getInputStream ()

String fileToRead = streamReader.readLine ()

BufferedReader fileReader = new BufferedReader (new FileReader (fileToRead))

String line = null

While (line = fileReader.readLine ())! = null)

StreamWriter.println (line)

FileReader.close ()

StreamWriter.close ()

StreamReader.close ()

} catch (FileNotFoundException e) {

System.out.println ("Could not find requested file on the server.")

} catch (IOException e) {

System.out.println ("Error handling a client:" + e)

}

}

Public static void processRequest (Socket requestToHandle) {

Synchronized (pool) {

Pool.add (pool.size (), requestToHandle)

Pool.notifyAll ()

}

}

Public void run () {

While (true) {

Synchronized (pool) {

While (pool.isEmpty ()) {

Try {

Pool.wait ()

} catch (InterruptedException e) {

Return

}

}

Connection = (Socket) pool.remove (0)

}

HandleConnection ()

}

}

}

The above is about the content of this article on "how to create a multi-threaded server in Java". I believe we all have a certain understanding. I hope the content shared by the editor will be helpful to you. If you want to know more about the relevant knowledge, please follow the industry information channel.

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