Had a very unusual requirement where I needed to share singleton between projects that requires initialization arguments. These arguments are different based on what server it is started. In applications using CDI this was very easy but not all where using CDI and a lot of the projects where not under my control they where simply using the lib. Thread safty was also a concern and I wanted to avoid using synchronized. Here is the solution I came up with.
I know having a init function and not using a Factory is a bit messy but it works. Just remember to mark the arguments as final to prevent other threads from reading stale data in the begining. Synchronized blocks is only called on initialized and on the first getInstance() calls until the “instance” vairable is set and visible by all threads. After that is is just like normal Singleton.