Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Asynchronous Processing in Java with Future and FutureTask

In this article we present the Future and FutureTask classes, which allow processing tasks asynchronously and in parallel with Java.

At the beginning of Java for programming asynchronous events, we used the Thread class and Runnable interface, which allowed the development of parallel applications. The problem is that you can not return a value to the end of the run. Thus, FutureTaks classes, and Future callable were added, which has more or less the same function of the preceding but rather facilitate the development of parallel applications. Look:

  • Future: Class that encapsulates a call made in parallel, and you can cancel the execution of a task, find out if the execution has ended successfully or error, among other operations;
  • FutureTask: It is an implementation of the Future interface running on a call in parallel. Also, with it you can make the same checks we do with the interface;
  • Callable: Interface to implement an execution in parallel. It is very similar to the Runnable interface, but this does not return any value, while the callable must return a value to the end of the run;
  • ExecutorService: Class for the execution of management at the same time, it creates a pool of threads, starting and canceling executions. You can also cancel this, thus avoiding the creation of new jobs.

To demonstrate in practice how to use them, this article will present some simple programs using the main features of each.

What is Socket

The first example shows how to implement a task in parallel only generates random numbers. This was done in GenerateRandomNumber class with the Callable interface. The method that should be implemented is the call() interface, which at the end of the run returns the value generated.

In the main it created a pool of threads and a task using the GenerateRandomNumber class in the variable task. Thus, this process is sent to the pool with the submit() method and this submission is returned a Future object type. With it expected to end in execution while, which is making sure that the thread has finished executing with isDone() method: this will happen when returned true. So the generated random value is returned. Finally, the returned value is printed on the console and the thread pool is finished with the shutdown() method. Listing 1 shows the code for this application.

Listing 1. Example using the Callable interface and the Future class

package future;
   
  import java.util.Random;
  import java.util.concurrent.Callable;
  import java.util.concurrent.ExecutionException;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.Future;
   
    public class Example1Print {
   
        private static final ExecutorService threadpool = Executors.newFixedThreadPool(3);
   
        public static void main(String args[]) throws InterruptedException, ExecutionException {
              GenerateRandomNumber task = new GenerateRandomNumber();
              System.out.println("Processing the task...");
              Future<Integer> future = threadpool.submit(task);
              while (!future.isDone()) {
                    System.out.println("The task was not processed yet!");
                    Thread.sleep(1); // sleep for 1 millisecond before checking again
              }
              System.out.println("Task complete!");
              long factorial = (long) future.get();
              System.out.println("The generated number was: " + factorial);
              threadpool.shutdown();
        }
   
        private static class GenerateRandomNumber implements Callable<Integer> {
   
              @Override
              public Integer call() {
                    Random rand = new Random();
                    Integer number = rand.nextInt(100);
                    return number;
              }
              
        }
  }

The result of the program is shown in Listing 2, where you can verify that the task is not run so it is submitted, then the main does not advance as it is not executed. When this happens, the generated number is printed on the screen.

Listing 2. Implementation of Listing 1

Processing the task ...
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet! 
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet! 
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 The task was not processed yet!
 Task complete!
 The generated number was: 27

Listing 3 shows an example a little higher, which calculates the factorial of a number on a task that will be performed in parallel. Note that the method returns a Long to the calculated value. The main method of this class is similar to the one in Listing 1.

The task is created in task variable and is sent to the parallel execution with the submit() method. When finished it is returned the calculated value that is printed on the screen.

The Factorial class is an implementation of the Callable interface and therefore implements the call() method, which aims to calculate the factorial of the number passed as a parameter. For this, it made a while statement that will multiply the value already calculated by a number and subtracting 1 from this until it arrives at 1.

Listing 3. Program to compute the factorial of a number of parallel

package future;
  import java.util.concurrent.Callable;
  import java.util.concurrent.ExecutionException;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.Future;
  import java.util.logging.Level;
  import java.util.logging.Logger;
   
   
  public class Example1 {
   
        private static final ExecutorService threadpool = Executors.newFixedThreadPool(3);
   
        public static void main(String args[]) throws InterruptedException, ExecutionException {
              
              Fatorial task = new Fatorial(20);
              System.out.println("Sending the task...");
              Future<Long> future = threadpool.submit(task);
              System.out.println("Task is submitted");
              while (!future.isDone()) {
                    System.out.println("The task was not finished yet...");
                    Thread.sleep(1); 
              }
              System.out.println("Task complete!");
              long factorial = (long) future.get();
              System.out.println("Fatorial of 10 is: " + factorial);
              threadpool.shutdown();
              
        }
   
        private static class Fatorial implements Callable<Long> {
              private final int number;
   
              public Fatorial(int number) {
                    this.number = number;
              }
   
              @Override
              public Long call() {
                    long output = 0;
                    try {
                          output = factorial(number);
                    } catch (InterruptedException ex) {
                          Logger.getLogger(Example1.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    return output;
              }
   
              private long factorial(int number) throws InterruptedException {
                    if (number < 0) {
                          throw new IllegalArgumentException("Number must be greater than zero");
                    }
                    long result = 1;
                    while (number > 0) {
                          result = result * number;
                          number--;
                    }
                    return result;
              }
        }
  }

Note that the previous two examples had only one thread running in parallel.

In Listing 4 we see the implementation of the code displayed.

Listing 4. Implementation of Listing 3

Sending the task...
 Task is submitted
 The task was not finished yet... 
 The task was not finished yet...
 The task was not finished yet...
 The task was not finished yet... 
 The task was not finished yet... 
 The task was not finished yet...
 The task was not finished yet...
 The task was not finished yet...
 The task was not finished yet...
 Task complete!
 Fatorial of 20 is: 2432902008176640000

We will increase a little complexity, which in Listing 5 are initiated three tasks also using GenerateRandomNumber class.

Note that the three tasks were created in the variables Task1, task2 and task3 and were sent to be executed with the submit() method.

At the end of the run is made the sum of the return of the three threads and this value is displayed on the console.

The implementation of this code is shown in Listing 6.

Listing 5. Adding values generated by multiple threads

package future;
  import java.util.Random;
  import java.util.concurrent.Callable;
  import java.util.concurrent.ExecutionException;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.Future;
   
  public class Example1Sum {
   
        private static final ExecutorService threadpool = Executors.newFixedThreadPool(3);
   
        public static void main(String args[]) throws InterruptedException, ExecutionException {
              
              GenerateRandomNumber task1 = new GenerateRandomNumber();
              GenerateRandomNumber task2 = new GenerateRandomNumber();
              GenerateRandomNumber task3 = new GenerateRandomNumber();
              
              System.out.println("Processing the task ...");
              Future<Integer> futureT1 = threadpool.submit(task1);
              Future<Integer> futureT2 = threadpool.submit(task2);
              Future<Integer> futureT3 = threadpool.submit(task3);
              
              
              
              while (!futureT1.isDone() && futureT2.isDone() && futureT3.isDone()) {
                    System.out.println("The tasks were not processed yet!");
                    Thread.sleep(1); // sleep for 1 millisecond before checking again
              }
              System.out.println("Task complete!");
              long valor = futureT1.get();
              valor = valor + futureT2.get() + futureT3.get();
              System.out.println("The sum of generated values is: " + valor);
              threadpool.shutdown();
        }
   
        private static class GenerateRandomNumber implements Callable<Integer> {
   
              @Override
              public Integer call() {
                    Random rand = new Random();
                    Integer number = rand.nextInt(100);
                    System.out.println("Generated value: " + number);
                    return number;
              }
              
        }
  }
You can see in Listing 6 that the three tasks are performed in parallel, each generating a single value. At the end of the three runs the three values are added together and this sum is displayed on the screen. Listing 6. Implementation of Listing 5
Processing the task ...
  The tasks were not processed yet!;
  The tasks were not processed yet!;
  The tasks were not processed yet!;
  The tasks were not processed yet!; 
  The tasks were not processed yet!;
  The tasks were not processed yet!;
  Task complete!
  Generated value: 21
  Generated value: 24
  Generated value: 49
  The sum of generated values is: 94
 

Listing7.ServerwithmultipleThreads
package future;
   
  import java.io.DataInputStream;
  import java.io.DataOutputStream;
  import java.io.IOException;
  import java.net.ServerSocket;
  import java.net.Socket;
  import java.net.SocketTimeoutException;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.Future;
   
  public class Server implements Runnable {
   
        private final ServerSocket serverSocket;
        private final ExecutorService pool;
   
        List<Future> requests = new ArrayList<Future>();
   
        public static void main(String args[]) throws IOException {
              System.out.println("Server on");
              new Thread(new Server(8000, 3)).run();
        }
   
        public Server(int port, int poolSize) throws IOException {
              serverSocket = new ServerSocket(port);
              pool = Executors.newFixedThreadPool(poolSize);
        }
   
        public void run() { // run the service
              try {
                    pool.execute(new CheckRequest(requests));
                    while (true) {
                          System.out.println("New request!");
                          Future req = pool.submit(new HandleRequest(serverSocket.accept()));
                          requests.add(req);
                    }
              } catch (IOException ex) {
                    pool.shutdown();
              }
        }
  }
   
  class CheckRequest implements Runnable {
        private final List<Future> requests;
   
        CheckRequest(List<Future> requests) {
              this.requests = requests;
        }
   
        public void run() {
              while (true) {
                    int sumDone = 0;
                    int sumCanceled = 0;
                    int sumEmExecution = 0;
                    try {
                          Thread.sleep(10000);
                          for (Future f : requests) {
                                if (f.isDone()) {
                                      sumDone++;
                                } else if (f.isCancelled()) {
                                      sumCanceled++;
                                } else if (!f.isDone()) {
                                      sumEmExecution++;
                                }
                          }
                          System.out.println("Done: " + sumDone);
                          System.out.println("Canceled: " + sumCanceled);
                          System.out.println("Execution: " + sumEmExecution);
                    } catch (InterruptedException e) {
                          e.printStackTrace();
                    }
              }
        }
  }
   
  class HandleRequest implements Runnable {
        private final Socket server;
   
        HandleRequest(Socket server) {
              this.server = server;
        }
   
        public void run() {
              try {
                    System.out.println("Connected to: " + server.getRemoteSocketAddress());
                    DataInputStream in = new DataInputStream(server.getInputStream());
                    System.out.println(in.readUTF());
                    DataOutputStream out = new DataOutputStream(server.getOutputStream());
                    Thread.sleep(5000);
                    out.writeUTF("You connection ended!");
                    server.close();
              } catch (SocketTimeoutException s) {
                    System.out.println("Socket timed out!");
              } catch (IOException e) {
                    e.printStackTrace();
              } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
              }
        }
  } 

Just to check the operation of server was implemented a simple client, as shown in Listing 8. The connection is made at the address localhost port 8000. Once connected, the client sends a message to the server and waits for the answer.

Listing 8. Client that connects to the server

package future;
   
  import java.io.DataInputStream;
  import java.io.DataOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.net.Socket;
   
  public class Cliente {
   
        public static void main(String[] args) {
              String serverName = "localhost";
              int port = 8000;
              try {
                    System.out.println("Starting a connection!");
                    Socket client = new Socket(serverName, port);
                    System.out.println("Connected to: " + client.getRemoteSocketAddress());
                    OutputStream outToServer = client.getOutputStream();
                    
                    DataOutputStream out = new DataOutputStream(outToServer);
                    out.writeUTF("Hello Server! " + client.getLocalSocketAddress());
                    
                    InputStream inFromServer = client.getInputStream();
                    DataInputStream in = new DataInputStream(inFromServer);
                    
                    System.out.println("Response: " + in.readUTF());
                    client.close();
              } catch (IOException e) {
                    e.printStackTrace();
              }
   
        }
  }

The result of the server implementation is shown in Listing 9, where you can check the various requests made by the client and the execution of the thread that examines the connection status. This status is always updated with the current server conditions. We see that in the first run this task does not yet exist any request, while in the second there were four executions pending and completed; already in the third there were five completed and three outstanding, and finally, in the last run all eight requests had been answered.

Listing 9. Implementation of Listing 8

Server no ar
 New request!
 Check the server status!
 Done: 0
 Canceled: 0
 Execution: 0
 New request!
 Connected a: /127.0.0.1:54841
 Hello Server! /127.0.0.1:54841
 New request!
 Connected a: /127.0.0.1:54842
 Hello Server! /127.0.0.1:54842
 New request!
 Connected a: /127.0.0.1:54845
 Hello Server! /127.0.0.1:54845
 New request!
 New request!
 Check the server status!
 Done: 1
 Canceled: 0
 Execution: 4
 Connected a: /127.0.0.1:54846
 Hello Server! /127.0.0.1:54846
 New request!
 Connected a: /127.0.0.1:54848
 Hello Server! /127.0.0.1:54848
 New request!
 Connected a: /127.0.0.1:54850
 Hello Server! /127.0.0.1:54850
 New request!
 Connected a: /127.0.0.1:54861
 Hello Server! /127.0.0.1:54861
 Check the server status!
 Done: 5
 Canceled: 0
 Execution: 3
 Connected a: /127.0.0.1:54889
 Hello Server! /127.0.0.1:54889
 Check the server status!
 Done: 8
 Canceled: 0
 Execution: 0

Just as a curiosity, the server response to the client is only a message that the connection is completed, as shown in the following code:

Starting the connection!
Connected to: localhost/127.0.0.1:8000
Answer: Your connection is over! Goodbye!

With FutureTask class and Callable interfaces and futere programming asynchronous tasks in Java became much easier, avoiding some "hacks" that were necessary for the implementation of this type of application.

I hope this article is helpful! To the next!

Links

FutureTask class documentation

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html

Future interface documentation

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html

the Callable interface documentation

http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html



Web developer and passioned for web design, SEO and front end technologies.

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login