In my previous post ( Understanding commons HttpClient with example.) , we discussed about the basics of HttpClient with an example . In this post we will learn how we can use HttpClient in a multi-threaded environment.
Example :
In this example , there are three separate threads making a GET request to three different URIs . For convenience , I have taken the URIs in an array .
Why use HttpClient in Multi-threaded environment ?
Now that's a good question . Suppose we need to download multiple files simultaneously .For example  in my project , we have 18 nodes on live environment . Sometimes we need to download log files from all the nodes for doing some log analysis . Now there are various options to do that . 
- The first approach is that we can download all the files one by one . Do you think that's a good approach ? I think I know your answer :)
- The second approach is we can use HttpClient with multiple threads to download all the log files concurrently .
So what is the problem now ?
For execution , each method requires an instance of  HttpConnection.  HttpConnection can only be safely used from a single thread and method at a time . Also connections are finite resources and they should be managed in a proper way . We need  to make sure that they are properly allocated to the methods that require them . 
OK Cool . But how are we going to do that ?
MultiThreadedHttpConnectionManager to the rescue .
Below code snippet shows how we can use it with HttpClient.
OK Cool . But how are we going to do that ?
MultiThreadedHttpConnectionManager to the rescue .
Below code snippet shows how we can use it with HttpClient.
MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); HttpClient client = new HttpClient(connectionManager);
Example :
In this example , there are three separate threads making a GET request to three different URIs . For convenience , I have taken the URIs in an array .
- Here instead of creating only HttpClient instance ( as in the previous blog ) , first an instance of MultiThreadedHttpConnectionManager is created and then its reference is passed to the HttpClient in constructor.
- Connection is released manually in the finally block .This is because HttpClient doesn't know when a method is not using a connection as method's response is not read directly by the HttpClient. The response is read using method's connection , so a connection can not be released until the response body is read which is after the HttpClient finishes executing the method.
package httpclient;
import java.io.IOException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.StatusLine;
import org.apache.commons.httpclient.methods.GetMethod;
public class MultiThreadedExample {
    public static void main(String[] args) {
        // Creating MultiThreadedHttpConnectionManager
        MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
        // Passing it to the HttpClient.
        HttpClient httpClient = new HttpClient(connectionManager);
        // URIs that needs to be GET by threads.
        String[] urisToGet = { "https://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search",
                "https://www.google.com/search?hl=en&q=servicemix&btnG=Google+Search",
                "https://www.google.com/search?hl=en&q=tomcat&btnG=Google+Search", };
        // create a thread for each URI
        for (int i = 0; i < urisToGet.length; i++) {
            GetMethod get = new GetMethod(urisToGet[i]);
            new CreateThread(httpClient, get, "Thread-" + i).start();
        }
    }
    static class CreateThread extends Thread {
        private final HttpClient httpClient;
        private final GetMethod method;
        public CreateThread(HttpClient httpClient, GetMethod method, String name) {
            super(name);
            this.httpClient = httpClient;
            this.method = method;
        }
        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + " - about to get something from "
                        + method.getURI());
                // Execute the method.  
                int statusCode = httpClient.executeMethod(method);
                if (statusCode != HttpStatus.SC_OK) {
                    System.err.println("Method failed: " + method.getStatusLine());
                }
                // Reading the status body.  
                StatusLine statusLine = method.getStatusLine();
                System.out.println(Thread.currentThread().getName() + " " + statusLine);
            } catch (HttpException e) {
                System.err.println("Fatal protocol violation: " + e.getMessage());
            } catch (IOException e) {
                System.err.println("Fatal transport error: " + e.getMessage());
            } finally {
                // Release the connection.  
                method.releaseConnection();
            }
        }
    }
}

 
 
 
No comments :
Post a Comment