I want to benefit from asynchronously calling one of my methods. Since I use spring framework, this task is quite trivial, so I just marked the method with #Async annotation.
However my method is using a global variable that is not intended to be used concurrently by multiple threads( you may think of it as javax.jms.Session).
First thing that comes to mind to mark the method with synchronized keyword in order to make sure that method is thread safe.
But on the other hand it will be completely nonsense to use #Async annotation on synchronized method, right?
Is there any benefit to use #Async annotation on method that contains synchronized block ?
The purpose of making something asynchronous is that it will do things in the future, that will take relatively much time, for example file or database operation, and during that time, you can make other useful operations.
In your case, if you do synchronous block inside and async operation, you will lose async functionality making that part of your code block in certain cases. Of course, if you access a shared resource concurrently, you should defend it, the real question here, is that you really need async functionality inside that function? Maybe you can refactor your code to deal with the synchronous resource somewhere else.
Also if you are really into async functionality, and spring, you should check out Spring 5, and what it has to offer, when it's released.
Spring 5.x
Related
A common advice in Java is to not to let the "this" reference escape during construction of an object and therefore not start any threads in a constructor. But I find myself writing a lot of classes that should start a thread using an executor. According to the common advice, I should write an extra start() method that submits the task to the executor.
But submitting a task to an executor gives happens-before guarantees as documented here. So would it be fine to submit the task in the last statement of the constructor? Or the more general question: is it safe to let "this" escape in the last statement of a constructor if that statement provides happens-before guarantees?
The Answer by Stefan Feuerhahn is correct.
I’ll add the suggestion that embedding an executor service within the class performing the work can be a “code smell”, an indication of weak design.
Generally we want to follow the single responsibility principle in our designs. A class should have a single purpose, and should try not to stray from that narrow specific purpose.
If, for example, a class were written to create a report, that class should know only about that report. That class should not know about when that report should be run, or how often to run the report, or what other code cares about if the report has been run.
Such scheduling of when to run the report is tied to the lifecycle of the app. For one important thing, the executor service must eventually be shut down when no longer needed or when the app is exiting. Otherwise the backing thread pool may continue indefinitely like a zombie 🧟. Your report-generating class should not know about when it is no longer needed, nor should it know about when or why the app is exiting.
Another aspect of the issue is that configuring an executor service involves knowing about the deployment scenario. How much RAM, how many CPU cores, how much other burden on that host machine, all contribute to decisions about how to set up the executor service(s). Your report-generating code should not have to change because of changes to your deployment situation.
The report-generating class should not know anything about the calling app’s lifecycle, not know anything about the executor service. The report-generating app should know nothing more than how to generate that one report. Some other place in your code, perhaps some report manager class or your app’s lifecycle orchestration code, should handle how often and when to run the report.
Yes, this is safe, because the statement providing happens-before guarantees will make sure all fields are correctly initialized visible to other threads. One caveat is that a subclass could ruin this safety so its better to make the class final. But, as Holger pointed out, even then an additional constructor delegating to the one that started the thread could harm safety.
The general advice "don't let this escape from the constructor" exists mainly because it is easier and thus less error prone to follow this rule then to keep all nuances in mind (like subclassing).
Trying to wrap service class with two aspects to get this call chain:
javanica..HystrixCommandAspect -> MyCustomAroundAspect -> MyService
met two problems:
HystrixCommandAspect does not call joinPoint.proceed(). Instead it calls method directly on target class, which effectively skips any other proxies created after javanica's aspect
Hystrix aspect makes subsequent calls running in deferent thread. It leads to message:
"No MethodInvocation found: Check that an AOP invocation is in progress, and that the ExposeInvocationInterceptor is upfront in the interceptor..."
which is reasonable because this interceptor keeps its stuff in thread local.
Questions:
1. Why is Spring APO implemented this way? Is it conceptually wrong to run different aspects in different threads? Are there workarounds except changing the aspects' order?
Why does HystrixCommandAspect call target class directly, but not through joinPoint.proceed()? Doesn't it break the contract (if one even exists)?
regards
Disclaimer: I am not a Spring or Hystrix user, just an AOP guy.
Why does HystrixCommandAspect call target class directly, but not through joinPoint.proceed()? Doesn't it break the contract (if one even exists)?
Actually, you have to ask the Hystrix maintainer. It is a good question, actually. the assumption that Hystrix aspects are the only ones in this universe is certainly a bold one because there actually is an AspectJ or Spring AOP contract for #Around advices:
Either the aspect calls the original method. If it does so, it ought to use proceed(). If it proceeds with the original method arguments or with a modified set, is up to the aspect. Also if it proceeds before, after or in between doing other things.
Or the aspect returns a result (for non-void methods) calculated without proceeding to the original method.
Or the aspect throws an exception, not returning any result.
Having said that, I think it is a design flaw in Hystrix not to pass on the ProceedingJoinPoint and eventually call proceed() on it in case the original method is to be called eventually. If I was a Hystrix user, I would open a bug ticket for that.
Besides, it is in principle no problem to call proceed() asynchronously from another thread in which you inject the joinpoint instance upon creation. Then you can put that thread (or a runnable) into a queue and execute it whenever convenient. Technically you can even call proceed() on the same joinpoint instance multiple times, but if the target method is no pure function without side effects you might want to be careful with that and usually won't do it unless your aspect implements some kind of retry scheme (with or without exponential back-off). So Hystrix could to that too. If they do not then they must be doing something ugly instead, such as use reflection to call the original method. I did not check.
Actually, I have two questions, although a bit related:
I know that unit tests should test the public API. However, if I have a close method that closes sockets and shuts down executors, however, neither sockets nor executors are exposed to users of this API, should I test if this is done, or only that the method executed without error? Where is the borderline between public api/behavior and impl details?
if I test a method that performs some checks, then queues a task on executor service, then returns a future to monitor operation progress, should I test both this method and the task, even if the task itself is a private method or otherwise not exposed code? Or should I instead test only the public method, but arrange for the task to be executed in the same thread by mocking an executor? In the latter case, the fact that task is submitted to an executor using the execute() method would be an implementation detail, but tests would wait for tasks to complete to be able to check if the method along with it's async part works properly.
The only question you should ask yourself is this: will I or my colleagues be able to change the code with confidence without these tests frequently executed. If the answer is no - write and maintain the tests as they provide value.
With this in mind you may consider refactoring your code so that the "low level plumbing" (e.g. socket and thread management) lives in a separate module where you treat it explicitly as part of the contract that module provides.
In a spring application when we receive message #Service persist bean is calling the database operation to insert in to database & parallel #Service to parse & process message. In this case persist is using #Transactional. In order to make the flow in parallel, is it advised to add #Async for persist.
Additionally there is #Aspect on each save method called by persist service for logging & audit.
Is #Async advisable for database operations?
Does #Async create table locks?
All that #Async does is cause the methods of the annotated component to be executed on another thread, where it gets the thread from a pool (which can be specified, so you can choose for some operations to have a dedicated pool).
#Async itself doesn’t do anything to lock database tables, or anything else database-related. If you want database-level locking you will have to implement that through some other means. If you want the call to use a transaction you have to use the #Transactional annotation on the component being called asynchronously. The transaction will be separate from the caller's transaction. Of course the transaction can possibly cause database locking depending on the isolation level and database implementation.
It’s tricky to use #Async with database work. One pitfall occurs with jpa persistent entities passed across threads, when they have a lazy property that gets realized in the new thread (where the proxy is now invalid because it can’t get to the entityManager from the old thread). It’s safer if the things passed between threads are immutable.
#Async adds complexity and is hard to reason about. There are opportunities for race conditions and deadlocks where if you don’t get it exactly right then bad things can happen, and you can’t count on testing to uncover the issues. It’s working without a net, if you want any infrastructure to help with exception handling, retries, or other recovery you will have to provide it yourself.
So no, I wouldn’t necessarily call it advisable. It's a good capability to have in your toolbox that might be helpful for a few isolated cases, but pervasive usage would seem like a bad thing. There are alternatives if you’re looking for ways to persist data without blocking.
Due to the deprecated nature of the Thread stop() and suspend() methods, I have become accustomed to implementing a standard cooperative suspension method using the well tested wait/notify methodology. Unfortunately my current project includes an initialisation thread that duplicates a recursive directory structure via a single call to an external method that doesn't return until it has finished and does not implement any kind of wait/notify cooperation.
I'm curious to know what other programmers are tempted to do in this situation, save perhaps reimplementing the external method, as I'm quite tempted to use the Thread.suspend() method and hope the file operations contained within the external method don't hold on to anything critical whilst suspended.
Hmmm...this is a tricky one.
Well do not even try stop() or suspend(). They were deprecated and there are reasons for rightly so. Ideally you shouldn't even be trying wait or notify when you have so many excellent libraries available in java.util.concurrent package.
In your case, you should check the documentation of the external method you are calling to know about the shutdown policy of that library. If none is mentioned then you can probably try interrupting. interrupt will surely work if the external method call makes some blocking calls. Other than it, I see no other way.
Using suspend will only lead to instability rather than aiding anything. Not using it will take more computational power but will be stable atleast.