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