10

I need to make a library in which I will have synchronous and asynchronous methods in it.

  • executeSynchronous() - waits until I have a result, returns the result.
  • executeAsynchronous() - returns a Future immediately which can be processed after other things are done, if needed.

Core Logic of my Library

The customer will use our library and they will call it by passing DataKey builder object. We will then construct a URL by using that DataKey object and make a HTTP client call to that URL by executing it and after we get the response back as a JSON String, we will send that JSON String back to our customer as it is by creating DataResponse object. Some customer will call executeSynchronous() and some might call executeAsynchronous() so that's why I need to provide two method separately in my library.

Interface:

public interface Client {

    // for synchronous
    public DataResponse executeSynchronous(DataKey key);

    // for asynchronous
    public Future<DataResponse> executeAsynchronous(DataKey key);
}

And then I have my DataClient which implements the above Client interface:

public class DataClient implements Client {

    private RestTemplate restTemplate = new RestTemplate();
    // do I need to have all threads as non-daemon or I can have daemon thread for my use case?
    private ExecutorService executor = Executors.newFixedThreadPool(10);

    // for synchronous call
    @Override
    public DataResponse executeSynchronous(DataKey key) {
        DataResponse dataResponse = null;
        Future<DataResponse> future = null;

        try {
            future = executeAsynchronous(key);
            dataResponse = future.get(key.getTimeout(), TimeUnit.MILLISECONDS);
        } catch (TimeoutException ex) {
            PotoLogging.logErrors(ex, DataErrorEnum.TIMEOUT_ON_CLIENT, key);
            dataResponse = new DataResponse(null, DataErrorEnum.TIMEOUT_ON_CLIENT, DataStatusEnum.ERROR);
            future.cancel(true); // terminating tasks that have timed out
        } catch (Exception ex) {
            PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
            dataResponse = new DataResponse(null, DataErrorEnum.CLIENT_ERROR, DataStatusEnum.ERROR);
        }

        return dataResponse;
    }

    //for asynchronous call
    @Override
    public Future<DataResponse> executeAsynchronous(DataKey key) {
        Future<DataResponse> future = null;

        try {
            Task task = new Task(key, restTemplate);
            future = executor.submit(task); 
        } catch (Exception ex) {
            PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
        }

        return future;
    }
}

Simple class which will perform the actual task:

public class Task implements Callable<DataResponse> {

    private DataKey key;
    private RestTemplate restTemplate;

    public Task(DataKey key, RestTemplate restTemplate) {
        this.key = key;
        this.restTemplate = restTemplate;
    }

    @Override
    public DataResponse call() {
        DataResponse dataResponse = null;
        String response = null;

        try {
            String url = createURL();
            response = restTemplate.getForObject(url, String.class);

            // it is a successful response
            dataResponse = new DataResponse(response, DataErrorEnum.NONE, DataStatusEnum.SUCCESS);
        } catch (RestClientException ex) {
            PotoLogging.logErrors(ex, DataErrorEnum.SERVER_DOWN, key);
            dataResponse = new DataResponse(null, DataErrorEnum.SERVER_DOWN, DataStatusEnum.ERROR);
        } catch (Exception ex) { // should I catch RuntimeException or just Exception here?
            PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
            dataResponse = new DataResponse(null, DataErrorEnum.CLIENT_ERROR, DataStatusEnum.ERROR);
        }

        return dataResponse;
    }

    // create a URL by using key object
    private String createURL() {
        String url = somecode;
        return url;
    }
}

I have few questions on my above solution -

  • Should I use daemon or non daemon threads for my above use case?
  • Also, I am terminating the tasks that have timed out so that it doesn't occupy one of my limited 10 threads for a long time. Does that look right the way I am doing it?
  • In my call() method, I am catching Exception. Should I catch RuntimeException there? What is the difference if I catch Exception or RuntimeException?

When I started working on this solution, I was not terminating the tasks that have timed out. I was reporting the timeout to the client, but the task continues to run in the thread pool (potentially occupying one of my limited 10 threads for a long time). So I did some research online and I found that I can cancel my tasks those have timed out by using cancel on future as shown below -

future.cancel(true);

But I wanted to make sure, does it look right the way I am doing in my executeSynchronous method to cancel the tasks that have got timedout?

Since I am calling cancel() on the Future which will stop it from running if tasks is still in the queue so I am not sure what I am doing is right or not? What is the right approach to do this?

If there is any better way, then can anyone provide an example for that?

Should we always be terminating the tasks that have got timed out? If we don't do that then what might be the impact I will have?

john
  • 11,311
  • 40
  • 131
  • 251
  • 1
    I did read only the beginning of the question (I'm not in the mood for code review, sorry), but here's a suggestion: add a single execute method to the client interface, which returns a Future. This way, it can be an implementation detail whether you implement it synchronously or asynchronously. – lbalazscs Mar 15 '15 at 20:43
  • This won't answer your questions, but have you already thought of providing two different implementations of the client interface (a synchronous and an asynchronous version) instead of having each method twice? – isnot2bad Mar 15 '15 at 22:36
  • I have a design like this since in my company there are some customer who only want to use sync method but there are some customer, they are only interested in async method so that's why I have both the method. Depending on what customer need they can use that method. This is also the same case with open source project like datastax java driver, they have sync and async writes, it's up to me which one I want to use. – john Mar 16 '15 at 04:59
  • @lbalazscs are you around? I wanted to check if I am doing right thing to cancel my tasks that got timed out? – john Mar 20 '15 at 00:39
  • @david I'm around but still no time for code review, and I guess you mean someone else anyway, because here I had only a small suggestion... But basically you can call get with timeout and if you get the TimeoutException, you call cancel. – lbalazscs Mar 20 '15 at 00:51
  • @lbalazscs sure that's what I am doing but do I need to deal with closing RestTemplate or need to do anything else for properly cancelling the thread? – john Mar 20 '15 at 01:03
  • Sorry, I have no time to understand what exactly you are trying to do, and without understanding it, I cannot answer such questions. Generally speaking, you should release all resources that are no longer needed. Also read carefully the javadoc for Future.cancel, and determine whether you meed to implement interruption support. – lbalazscs Mar 20 '15 at 01:17
  • You're trying to do too much. They can easily do this themselves using the java concurrency package and the RestTemplate. They may benefit from a good code sample, but don't constrain them by creating a library that makes all the decisions for them. – flup Mar 26 '15 at 21:43
  • @flup Thanks for feedback. I was not able to understand how I can do that using java concurrency package and RestTempale? Do you see any better way to do this? – john Mar 26 '15 at 23:02
  • @david There's not so much something wrong with what you do as that you constrain your users from figuring out what suits them best. An example of what their code could look like is on https://spring.io/guides/gs/async-method/ – flup Mar 26 '15 at 23:09

2 Answers2

8

Should I use daemon or non daemon threads for my above use case?

It depends on whether or not you want these threads to stop the program from exiting. The JVM will exit when the last non-daemon thread finishes.

If these tasks can be killed at any time if the JVM exists then they should be daemon. If you want the JVM to wait for them then make them non-daemon.

See: java daemon thread and non-daemon thread

Also, I am terminating the tasks that have timed out so that it doesn't occupy one of my limited 10 threads for a long time. Does that look right the way I am doing it?

Yes and no. You are properly calling cancel() on the Future which will stop it from running if it is still in the queue. However, if the thread is already running the task then the cancel will just interrupt the thread. Chances are that the restTemplate calls are not interruptible so the interrupt will be ignored. Only certain methods (like Thread.sleep(...) are interruptible and throw InterruptException. So calling future.cancel(true) won't stop the operation and terminate the thread.

See: Thread not interrupting

One thing you could do is to put a cancel() method on your Task object which forcefully closes the restTemplate. You will need to experiment with this. Another idea is to set some sort of timeout on the restTemplate connection or IO so it doesn't wait forever.

If you are working with the Spring RestTemplate then there is not a direct close but you can close the underlying connection I believe which may be via the SimpleClientHttpRequestFactory so you will need to call disconnect() on the underlying HttpURLConnection.

In my call() method, I am catching Exception. Should I catch RuntimeException there?

RuntimeException extends Exception so you will already catch them.

What is the difference if I catch Exception or RuntimeException?

Catching Exception catches both the checked (non-runtime) exceptions and the runtime exceptions. Catching just the RuntimeException will mean that any defined exceptions will not be caught and will be thrown by the method.

RuntimeExceptions are special exceptions that do not need to be checked by the code. For example, any code can throw an IllegalArgumentException without defining the method as throws IllegalArgumentException. With checked exceptions, it is a compiler error if a checked exception is not caught or thrown by the caller method but this is not true with RuntimeExceptions.

Here's a good answer on the topic:

Community
  • 1
  • 1
Gray
  • 115,027
  • 24
  • 293
  • 354
  • Thanks for detailed suggestion. There is no performance issue if I use daemon or non daemon thread right? I understood regarding my third point which is Exception related. I am confuse regarding Timeout one. I was in the impression that suppose if my tasks got timedout, then I can cancel that task? What I am looking for is, let's say if one of my tasks got timedout then that means I am not interested in it so how can I cancel it? – john Mar 17 '15 at 18:26
  • No performance difference btw daemon threads and non-daemon @david. – Gray Mar 19 '15 at 14:18
  • Read more about thread interrupting @david. It is difficult to properly cancel a thread. You will need to close the `RestTemplate` which I mention in my response. – Gray Mar 19 '15 at 14:20
  • sure but what I don't close the rest template and just call cancel on the future if it is timed out? – john Mar 20 '15 at 00:59
  • As I mention in the answer @david, just calling `cancel` on the `Future` most likely won't do anything. – Gray Mar 20 '15 at 13:59
3

Should I use daemon or non daemon threads for my above use case?

It depends. But in this case I would prefer daemon threads because it is convenient to use clients which allows the process to exit.

Does that look right the way I am doing it?

No, it doesn't. Interrupting of an IO task is pretty hard. Try to set timeout in RestTemplate too. Canceling of the future in this case seems meaningless.

What is the difference if I catch Exception or RuntimeException?

If you don't have checked exceptions in try blocks there is no difference :) Just because only RuntimeExceptions possible in that case.

And one more important note: implementing sync call as async + waiting is bad idea. It is meaningless and consumes one thread from the thread pool per a call. Just create instance of the Task and call it in current thread!

Denis Borovikov
  • 737
  • 5
  • 9
  • Thanks for the help. Regarding my second question, can you help me to understand how can I set the timeout in `RestTemplate` efficiently? Since this library will have very high load and needs to respond back pretty fast. Meaning whatever time server is taking, it should take that much only. – john Mar 26 '15 at 21:20
  • Take a look: http://stackoverflow.com/questions/13837012/spring-resttemplate-timeout – Denis Borovikov Mar 27 '15 at 09:52
  • And if your load is really high I would recommend you to use async client as base for your library - it doesn't block thread. For example: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/AsyncRestTemplate.html or https://github.com/AsyncHttpClient/async-http-client – Denis Borovikov Mar 27 '15 at 09:56
  • Thanks for suggestiong `AsyncRestTemplate`. Do you think if I use aynchttpclient, then it will be useful in my case? Can you explain me why it will be better for my use case? This will help me to understand better why AsyncHttpClient is better. And if possible, can you provide an example using `AsyncRestTemplate`, how my code will look like? – john Mar 28 '15 at 03:17
  • I also have decided to directly call my Task class from executeSync method as well. – john Mar 28 '15 at 03:17
  • >it will be useful in my case Yes, it will. AsyncRestTemplate is based on the async apache client which is non-blocking. Non-blocking client releases the thread after sending the request, and acquires it whent the response given. It is wery efficient: you can send hundreds of parallel request using only one thread! Take a look to example: http://www.concretepage.com/spring-4/spring-4-asyncresttemplate-listenablefuture-example. As you can see it is returns future. – Denis Borovikov Mar 28 '15 at 12:25
  • understood so if I decide to use AsyncRestTemplate, do I still need to use ExecutorsService or not? As I still need to provide two methods, executeSynchronous and executeAsynchronous method so that customer can use what they want to use. – john Mar 28 '15 at 19:08
  • >do I still need to use ExecutorsService or not - No, you don't. >As I still need to provide two methods - you can use both AsyncRestTemplate and RestTemplate. Also you can wait on future, in case of non-blocking AsyncRestTemplate it is not so bad because it blocks only current thread, not thread from executor. – Denis Borovikov Mar 28 '15 at 19:48
  • hey are you around? Let's chat [here](http://chat.stackoverflow.com/rooms/74005/room-for-david-and-denis-borovikov). I have few basic questions. – john Apr 09 '15 at 22:54