4 Using Concurrency API For Networking

Pravin Jain

epgp books

 

Introduction

 

In the last module, we have seen how a simple multi-threaded network server can be created using the Thread class in Java. In that module we had seen a demo of using Thread class and Runnable to create a multi-threaded EchoServer. Since Java 5 we have a concurrency API available in Java to have better control over the concurrency. In this module we will look at how to create a EchoServer, using this high-level concurrency API.

 

New concurrency API

 

In new concurrency API, we have the a few useful interfaces. The task to be performed can now also be specified by using Callable instead of just Runnable. We also have an interface called ExecutorService, which will take care of the concurrency. We do not have to create new thread of execution by using the Thread class. Concurrency will be taken care by the ExecutorService.

 

We have different kinds of implementations for ExecutorService, to handle different kinds of concurrency requirements. We simply have to create objects of Callable or Runnable and then submit these to the ExecutorService. The ExecutorService takes care of concurrency and managing the various threads of execution. The ExecutorService also has methods to take care of shutting down all the tasks which were submitted.

 

When we submit any task to the ExecutorService in form of Callable or Runnable, then the submit method returns an instance of Future. The instance of Future can then subsequently be used to know about the state of the task which was submitted. Whether the task has been initiated or not, whether it has completed, and if it has completed, then what is the result. In order to create instance of ExecutorService, we can take the help of static methods available in the Executors class.

 

eg. in our case we may be interested in having concurrency, but we would like have a maximum limit on how many parallel threads we can have, so we may use the method newFixedThreadPool method. Another thing in this API is the Callable as an alternate of Runnable. The Callable has two significant differences from the Runnable. One, its call method has a generic return type, unlike returning of void by run method and secondly, it has a throws for Exception allowing for overriding methods to include a throws clause.

 

Demo for using concurrency API.

 

Now we demonstrate how we can use the concurrency API for creating EchoServer. In this demo we will use the existing multi-threaded EchoServer and use the concurrency API. We will demonstrate how to convert an existing multi-threaded application, which has its Runnable, into using the concurrency API for a better control over the concurrency requirement and how it makes the things easier.

 

Here we use the same Runnable as in the previous module. The source code of the Runnable is again included here for reference.

 

Source code of Echoer class

 

package org.epgpathshala.dad.net;

 

Developing the Server

 

In our server application here, the task for the main thread will be to start listening on the TCP/IP port and wait for a client to connect. Whenever a client connects we need to need to handle the client connection, for which we will need a separate thread. We can create the Runnable object to handle the client connection and continue accept the next connection. Lets call this as EchoServer.

 

So we develop the class EchoServer as a class with the main method . This EchoServer class has instance variables for an instance of ServerSocket and an ExecutorService. In the constructor, we will initialize the ServerSocket instance variable by calling the constructor of ServerSocket and we will initialize the instance of ExecutorService by calling the static method in Executors. We also have the run() method which is a while true loop, accepting a new connection, creating the Runnable(Echoer) object and submitting it to the ExecutorService, and then accepting the new connection again. The man method is simply used for creating the instance of EchoServer and calling the run method.

 

Source code of EchoServer class

 

package org.epgpathshala.dad.net;

 

import java.net.ServerSocket; import java.net.Socket; import java.io.IOException;

import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future;

 

public class EchoServer { private ServerSocket board;

private ExecutorService executor;

public EchoServer(int port, int poolSize) throws IOException{

this.board = new ServerSocket(port);

this.executor = Executors.newFixedThreadPool(poolSize);

}

public void run() throws IOException {

while(true) {

Socket phone = this.board.accept();

Echoer echoer = new Echoer(phone);

//                  Thread thread = new Thread(echoer);

//                  thread.start();

Future<?> future = this.executor.submit(echoer);

}

}

public static void main(String[] args) throws IOException {

int port = Integer.parseInt(args[0]);

int poolSize = Integer.parseInt(args[1]);

//      EchoServer server = new EchoServer(port);

EchoServer server = new EchoServer(port, poolSize); server.run();

}

}

you can view video on Using Concurrency API For Networking
Suggested Reading:
1. Core Java Volume 2 by Cay Horstmann & Gary Cornell, Ninth Edition, Pearson Education.
2. Concurrent Programming in Java: Design Principles and Pattern (2nd Edition) by Doug Lea. Pearson Education
3. Concurrency in Practice by Brian Goetz, Pearson Education
4. https://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html