How to better use ExecutorService in multithreading environment?

a 夏天 提交于 2019-12-05 01:29:36

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!

Gray

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:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!