Skip to content
Davide Maestroni edited this page Oct 26, 2016 · 19 revisions

##Overview

The wiki pages available in this section are meant to provide a deeper understanding of the JRoutine library features and how the project has been structured.

  • Build instructions are available to support cloning and forking of the project
  • Change log page records all the modifications introduced in each release
  • Usage examples give a quick overview on all the way in which a routine can be created and invoked
  • A Proguard dedicated page presents a few hints about the rules to be added to ensure a correct behaviour of the library code

##Notes

###About immutability, weak references and synchronization

The JRoutine library has been designed to let the user forget about threads, concurrency and synchronization, and focus instead on the implementation of the business logic. However, even if all the best practices has been put in place so to avoid starvation, deadlocks and race conditions, it is still possible for such issues to occur in case the library is not used in the correct way.

####Data immutability

Special caution must be taken so that data passed to channels are immutable objects or are treated as they were. In case the same object is changed after it's been passed to a channel, a concurrent modification may occur in a different thread, thus leading to unexpected results. It is good practice to choose the input and output types so that they are immutable by definition (like String, primitive types, unmodifiable collections or even immutable custom objects), or at least to ensure that, during the routine invocation lifecycle, they are just read and never modified. For example, if the invocation needs to modify an input which is an instance of a mutable object, a local copy should be made and modified instead, before returning it as a result. This behavior will prevent inconsistencies when changing the way routines are invoked or combined.

The very same considerations apply to the arguments passed as parameters to invocation factories. Immutability is the key to prevent any race condition.

####Memory leaks

Another topic needing particular attention is the leaking of memory. Instances passed as arguments to the library APIs might be retained by separate threads for a long period of time (depending in most cases on the timeouts set by the user). That will prevent the JVM garbage collector to effectively release the allocated memory. Routine builders try to cope with the issue by retaining a weak reference to the target object instead of a strong one, but, in many cases, such as invocation factory parameters or output consumers bound to a channel, it is up to the caller to avoid leaks. The user should also keep in mind that the asynchronous invocation of routines might happen with an unpredictable delay, depending, for instance, on the machine load at the time of the invocation. So, it is advisable to take precautions when handling objects whose lifecycle is managed by the specific platform or operating system.

####Synchronization

The last topic to take into consideration is synchronization. Even though the library provides automatic synchronization mechanisms, it's easy to forget that the code inside registered objects, like invocations or output consumers, are likely to be executed in threads which are different from the calling one. When creating, for instance, an anonymous class, the user must keep in mind that the reference to the objects visible inside the scope of the instantiation are automatically accessible and retained by the instance. In such case, it is important for the user to avoid using the implicit references or to protect them with some kind of synchronization.

Clone this wiki locally