I have a REST API where I am supposed to fetch large amount of data from an external API. I decided to try multi-threading to optimize the whole fetch-parse-persist cycle. But I am facing trouble with ExecutorService (I have not used it prior to this work). I am sharing the classes and relevant part of whole process
public class LogRetrievingService implements Runnable {
CustomHttpClient client;
public LogRetrievingService(CustomHttpClient client) {
this.client = client;
}
#Override
public void run() {
Response response = client.invokeExternalApi();
parse(response.readEntity(bytes[].class);
}
//skipping parse() for brevity, it basically selects some columns and sends them to DBwriter
My REST API resource is like this
public class LogRetrieverResource {
private CustomHttpClient client;
public LogRetrieverResource(CustomHttpClient client) {
this.client = client;
}
//this does not work
public void initLogRetrieval() {
ExecutorService service = Executors.newFixedThreadPool(4); //max_thread
for(int i = 0; i < 4; i++) {
service.submit(new LogRetrievingService (client));
}
}
//THIS WORKS
public void initLogRetrieval() {
for(int i = 0; i < 4; i++) {
Thread thread = new Thread(new LogRetrievingService(client));
thread.start();
}
}
}
Now when I hit my resource nothing happens, I can see that client's logs are hit but it does not go and fetch the data.
However if inside the loop of my LogRetrieverResource class I create a new Thread instance with same run method then multithreaded data fetching works as expected. Could someone point me in what am I doing wrong? I have no prior experience of using multithreading in java other than implementing the Runnable interface method.
edit: Adding client class details
import javax.ws.rs.client.Client;
public class CustomHttpClient {
public Response invokeExternalAPI() {
return client
.target("url") //removing url for confidentiality
.request()
.accept(MediaType.APPLICATION_JSON)
.cookie("SSO",<token>)
.get();
}
}
Just trying to notice the differences, and there shouldn't be much difference. First at the end of your executor submission loop add service.shutdown(). Then you will pretty much be doing exactly the same thing.
The next issue, exceptions are handled a bit differently. An executor service will capture all of the exceptions. For debugging purposes you can try.
service.submit(
() -> {
try{
new LogRetrievingService (client).run();
} catch(Exception e){
//log the exception so you can see if anything went wrong.
}
});
This is not the way to handle exceptions with an ExecutorService though, you should grab the future that you submitted and use that to handle any errors. Also, I suspect spring has some tools for doing this type of work.
Related
My application starts couple of clients which communicate with steam. There are two types of task which I can ask for clients. One when I don't care about blocking for example ask client about your friends. But second there are tasks which I can submit just one to client and I need to wait when he finished it asynchronously. So I am not sure if there is already some design pattern but you can see what I already tried. When I ask for second task I removed it from queue and return it here after this task is done. But I don't know if this is good sollution because I can 'lost' some clients when I do something wrong
#Component
public class SteamClientWrapper {
private Queue<DotaClientImpl> clients = new LinkedList<>();
private final Object clientLock = new Object();
public SteamClientWrapper() {
}
#PostConstruct
public void init() {
// starting clients here clients.add();
}
public DotaClientImpl getClient() {
return getClient(false);
}
public DotaClientImpl getClient(boolean freeLast) {
synchronized (clients) {
if (!clients.isEmpty()) {
return freeLast ? clients.poll() : clients.peek();
}
}
return null;
}
public void postClient(DotaClientImpl client) {
if (client == null) {
return;
}
synchronized (clientLock) {
clients.offer(client);
clientLock.notify();
}
}
public void doSomethingBlocking() {
DotaClientImpl client = getClient(true);
client.doSomething();
}
}
Sounds like you could use Spring's ThreadPoolTaskExecutor to do that.
An Executor is basically what you tried to do - store tasks in a queue and process the next as soon the previous has finished.
Often this is used to run tasks in parallel, but it can also reduce overhead for serial processing.
A sample doing it this way would be on
https://dzone.com/articles/spring-and-threads-taskexecutor
To ensure only one client task runs at a time, simply set the configuration to
executor.setCorePoolSize(1);
executor.setMaxPoolSize(1);
I'm testing a Web application written in Java EE using servlets (version 7). I'm sending a lot of HTTP requests to my servlets and I want to know when all requests are completed.
To send requests I'm using an executor. Also I don't know if it is the most efficient way to do this.
for (int i=0; i < numRequests; i++) {
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<util.Response> responseFromServlet = null;
responseFromServlet = executor.submit(new util.Request(new URL(url)));
if ( i != numRequests -1 ) {
executor.shutdown();
} else {
responseFromServlet.get().getBody(); // suspensive call for last invocation
executor.shutdown();
}
}
Actually the executor waits the end of the last invoked HTTP request but it usually is not the last one that completes.
I think that creating a new thread waiting for response of each HTTP servlet is crazy. I can't generate 100-200-300 threads, one for each request!
So is there a way to understand when all servlets end their execution? If needed, I can modify my servlets.
=== Edit ===
To be more precise, here is the Request class implementation:
public class Request implements Callable<Response> {
private URL url;
public Request(URL url) {
this.url = url;
}
#Override
public Response call() throws Exception {
return new Response(url.openStream());
}
}
And this it the Response class:
public class Response {
private InputStream body;
public Response(InputStream body) {
this.body = body;
}
public InputStream getBody() {
return body;
}
}
Using an executor is fine, you may want to increase the size of the ThreadPool though to have more concurrent threads performing your requests.
Use a CoutnDownLatch initialised with numRequests which sits waiting for all the threads to complete.
util.Request must call latch.countDown() in its runmethod
The code would look like this (handwritten - not tested)
ExecutorService executor = Executors.newFixedThreadPool(n);
final CountDownLatch latch = new CountDownLatch(numRequests);
for (int i=0; i < numRequests; i++) {
executor.submit(new util.Request(new URL(url), latch));
}
latch.await(someValue, TimeUnit.SECONDS)
`
Edit
Re-implement util.Request doing something like
public class Request implements Callable<Response> {
final private URL url;
final private CountDownLatch latch;
public Request(URL url, CountDownLatch latch) {
this.url = url;
this.latch = latch;
}
#Override
public Response call() throws Exception {
try {
return new Response(url.openStream());
}
catch (Exception e) {
//do something useful
}
finally {
latch.countDown();
}
}
}
You may want to consume the stream of you response before you countDown the latch to verify that you get what you expect as a response from your server.
If you are using this program to perform a load test, or even otherwise, I'd highly recommend that you use Jmeter instead. Jmeter already does what you are attempting to do and there are many plugins that will allow you to schedule the load / number of thread / time period etc. You can also monitor all HTTP requests through a variety of graphs.
Writing a test for your servlet should take you less than 5 minutes. The graphs are also easy to generate.
If you'd still like to use your custom program to contact the servlet, you can always limit the number of requests and back them up with a blocking queue through a threadpool executor.
Lastly, do not modify the servlet. You should be able to monitor it as a black box.
My current code uses series of asynchronous processes that culminate in results. I need to wrap each of these in such a way that each is accessed by a synchronous method with the result as a return value. I want to use executor services to do this, so as to allow many of these to happen at the same time. I have the feeling that Future might be pertinent to my implementation, but I can't figure out a good way to make this happen.
What I have now:
public class DoAJob {
ResultObject result;
public void stepOne() {
// Passes self in for a callback
otherComponent.doStepOne(this);
}
// Called back by otherComponent once it has completed doStepOne
public void stepTwo(IntermediateData d) {
otherComponent.doStepTwo(this, d);
}
// Called back by otherComponent once it has completed doStepTwo
public void stepThree(ResultObject resultFromOtherComponent) {
result = resultFromOtherComponent;
//Done with process
}
}
This has worked pretty well internally, but now I need to map my process into a synchronous method with a return value like:
public ResultObject getResult(){
// ??? What goes here ???
}
Does anyone have a good idea about how to implement this elegantly?
If you want to turn an asynchronous operation (which executes a callback when finished), into a synchronous/blocking one, you can use a blocking queue. You can wrap this up in a Future object if you wish.
Define a blocking queue which can hold just one element:
BlockingQueue<Result> blockingQueue = new ArrayBlockingQueue<Result>(1);
Start your asynchronous process (will run in the background), and write the callback such that when it's done, it adds its result to the blocking queue.
In your foreground/application thread, have it take() from the queue, which blocks until an element becomes available:
Result result = blockingQueue.take();
I wrote something similar before (foreground thread needs to block for an asynchronous response from a remote machine) using something like a Future, you can find example code here.
I've done something similar with the Guava library; these links might point you in the right direction:
Is it possible to chain async calls using Guava?
https://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained
If you like to get your hands dirty, you can do this
ResultObject result;
public void stepOne()
otherComponent.doStepOne(this);
synchronized(this)
while(result==null) this.wait();
return result;
public void stepThree(ResultObject resultFromOtherComponent)
result = resultFromOtherComponent;
synchronized(this)
this.notify();
Or you can use higher level concurrency tools, like BlockingQueue, Semaphore, CountdownLatch, Phaser, etc etc.
Note that DoAJob is not thread safe - trouble ensured if two threads call stepOne at the same time.
I recommend using invokeAll(..). It will submit a set of tasks to the executor, and block until the last one completes (successfully/with exception). It then returns a list of completed Future objects, so you can loop on them and merge the results into a single ResultObject.
In you wish to run only a single task in a synchronous manner, you can use the following:
executor.invokeAll(Collections.singleton(task));
--edit--
Now I think I understand better your needs. I assume that you need a way to submit independent sequences of tasks. Please take a look at the code I posted in this answer.
Bumerang is my async only http request library which is constructed for Android http requests using Java -> https://github.com/hanilozmen/Bumerang . I needed to make synchronous calls without touching my library. Here is my complete code. npgall's answer inspired me, thanks! Similar approach would be applied to all kinds of async libraries.
public class TestActivity extends Activity {
MyAPI api = (MyAPI) Bumerang.get().initAPI(MyAPI.class);
BlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<Object>(1);
static int indexForTesting;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
for(int i = 0; i < 10; i++) {
getItems();
try {
Object response = blockingQueue.take(); // waits for the response
Log.i("TAG", "index " + indexForTesting + " finished. Response " + response.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
t.start();
}
void getItems() {
Log.i("TAG", "index " + ++indexForTesting + " started");
api.getItems(new ResponseListener<Response<List<ResponseModel>>>() {
#Override
public void onSuccess(Response<List<ResponseModel>> response) {
List<ResponseModel> respModel = response.getResponse();
try {
blockingQueue.put(response);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void onError(Response<List<ResponseModel>> response) {
Log.i("onError", response.toString());
try {
blockingQueue.put(response);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
I'm looking for an example of how to make an asynchronous request in Java using Thrift. Looking at the generated code this seems to be possible, but I can't find a single example of how.
Here is an example of generated code that suggest the existence of an Asynchronous interface:
...
AsyncIface {
public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
private org.apache.thrift.async.TAsyncClientManager clientManager;
private org.apache.thrift.protocol.TProtocolFactory protocolFactory;
public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
this.clientManager = clientManager;
this.protocolFactory = protocolFactory;
}
public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
return new AsyncClient(protocolFactory, clientManager, transport);
}
}
...
Any pointer on how to use it?
Use the above interface to make the async call like this (The code mentions Cassandra but will easily generalize to your application):
TNonblockingTransport transport = new TNonblockingSocket("127.0.0.1", 9160);
TAsyncClientManager clientManager = new TAsyncClientManager();
TProtocolFactory protocolFactory = new TBinaryProtocol.Factory();
Cassandra.AsyncClient client = new Cassandra.AsyncClient(protocolFactory, clientManager, transport);
Cassandra.method_call(parameters, new Callback());
You haven't given any context, so I'll give you the basic parts you'll need:
To perform an asynchronous call, you'll need make it in a thread
To get the result, you'll need some kind of call back
The following represents a basic example of these elements in play:
final MyClient client; // Who will get a call back to the their sendResult() method when asynch call finished
ExecutorService executor = Executors.newSingleThreadExecutor(); // Handy way to run code in a thread
Runnable task = new Runnable() {
public void run() { // Where the "do the call" code sits
int result = someService.call(someParamter);
client.sendResult(result); // For example, expecting an int result
}
};
executor.submit(task); // This scheduled the runnable to be run
I read answers from similar Q&A
How do you create an asynchronous HTTP request in JAVA? |
Asynchronous programming design pattern |
AsyncTask Android - Design Pattern and Return Values
I see a lot of solutions , but none really satifies me.
Listener way
Once the results are caught, the processing is implemented in onResult method.
public interface GeolocationListener {
public void onResult(Address[] addresses);
public void onError(Exception e);
}
This solution doesn't quite satify me , because I want to handle the results in the main method. I hate this interface because when the response is returned, it is processed in onResult resulting in chains of processing and no way to go back to the "main" method.
The servlet way
public class SignGuestbookServlet extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
// ...
resp.sendRedirect("/guestbook.jsp");
}
}
There is no exposed Java code calling the servlet. All the configuration is done in the web.xml
The way I want
Wait for the response like this
Response a = getResponse();
// wait until the response is received, do not go further
// process
Response b = getResponse();
// wait until the response is received, do not go further
process(a,b);
Is there a design pattern to handle the async request and wait for the response like above ? Other way than the listener.
Please no library or framework.
EDIT
Thanks so far the responses. I didn't give you the full picture so I exposed the Geolocation class
I started the implementation . I don't know how to implement the method . Can someone shows "how to" ? He (or she) must also implement the listener to retrieve the results
private Address getFullAddress (String text, AddressListener listener, ... ){
// new Geolocation(text, listener, options).start()
// implements Geolocation.GeolocationListener
// how to return the Address from the onResult ?
}
First, you should not reject the first two methods you discuss. There are very good reasons people are using those techniques and you should try to learn them instead of creating new ones.
Otherwise, you should look at java.util.concurrent:
ExecutorService es = Executors.newFixedThreadPool(2);
...
Future<Response> responseA = es.submit(responseGetter);
Future<Response> responseB = es.submit(responseGetter);
process(responseA.get(), responseB.get());
where responseGetter is of type Callable<Response> (you must implement the method public Response call()).
Asynchronous code can always be made synchronous. The simplest/crudest way is to make the async call, then enter a while loop that just sleeps the current thread until the value comes back.
Edit: Code that turns an asynchronous callback into synchronous code--again, a crude implementation:
import java.util.concurrent.*;
public class MakeAsynchronousCodeSynchronous {
public static void main(String[] args) throws Exception {
final Listener listener = new Listener();
Runnable delayedTask = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new IllegalStateException("Shouldn't be interrupted", e);
}
listener.onResult(123);
}
};
System.out.println(System.currentTimeMillis() + ": Starting task");
Executors.newSingleThreadExecutor().submit(delayedTask);
System.out.println(System.currentTimeMillis() + ": Waiting for task to finish");
while (!listener.isDone()) {
Thread.sleep(100);
}
System.out.println(System.currentTimeMillis() + ": Task finished; result=" + listener.getResult());
}
private static class Listener {
private Integer result;
private boolean done;
public void onResult(Integer result) {
this.result = result;
this.done = true;
}
public boolean isDone() {
return done;
}
public Integer getResult() {
return result;
}
}
}
You could also use a CountDownLatch as recommended by hakon's answer. It will do basically the same thing. I would also suggest you get familiar with the java.util.concurrent package for a better way to manage threads. Finally, just because you can do this doesn't make it a good idea. If you're working with a framework that's based on asynchronous callbacks, you're probably much better off learning how to use the framework effectively than trying to subvert it.
Could CountDownLatch help you? In the main method, you call getResponse and then countDownLatch.await(). Pass a count down latch to the getResponse method and then count down once getResponse the result from getResponse is finished:
CountDownLatch latch = new CountDownLatch(1);
Response a = getResponse(latch);
latch.await();
latch = new CountDownLatch(1);
Response b = getResponse(latch);
latch.await();
process(a, b);
Your getResponse needs to call latch.countDown() once it's asynch parts return a result.
e.g.:
public Response getResponse(CountDownLatch latch) {
someAsychBloc(final CountDownLatch latch) {
do work
latch.countDown();
}
}
Essentially you need a "listener" of sorts no matter what. This is because you do not know WHEN your return message will come back, if at all (that is one of the downsides of asynchronous processing...what to do if you do not get a return message).
So you either need to implement a listener that waits for events (ie, it is nudged by the returning message to be processed).
Or you could do a hybrid on that by having a separate thread that "polls" (or pulls) a response area on your service to see if the return message exists.
So it really comes down to whether you want more of a "pull" or "push" method of retrieving messages.
The SCA (Service Component Architecture) framework might be something to consider, but depending on what you are doing, it could be overkill too. But something to consider.
EDIT:
I just found this in the Java SE 6 Javadocs that may be helpful. The
interface CompletionService which abstracts the very thing you care
about --> asynchronous work. I suggest you take a look.
If you want a page flow in a web application, you have to handle in the web way : storing some data either in the session, or cookies or hidden fields, etc.
The problem you're trying to tackle, as far as I understand it, doesn't come from asynchronousness but from the stateless http protocole.
Regards,
Stéphane