java - Do Guice singletons honor thread-confinement? -


i have concern regarding guice , whether or not singletons obey thread confinement may try set up:

public class cachemodule extends abstractmodule {     @override     protected void configure() {         // widgetcache.class located inside 3rd party jar         // don't have ability modify.         widgetcache widgetcache = new widgetcache(...lots of params);          // guice reuse same widgetcache instance on , on across         // multiple calls injector#getinstance(widgetcache.class);         bind(widgetcache.class).toinstance(widgetcache);     } }  // cacheadaptor "root" of dependency tree. other objects // created it. public class cacheadaptor {     private cachemodule bootstrapper = new cachemodule();      private widgetcache widgetcache;      public cacheadaptor() {         super();          injector injector = guice.createinjector(bootstrapper);          setwidgetcache(injector.getinstance(widgetcache.class));     }      // ...etc. } 

so can see, time create new instance of cacheadaptor, cachemodule used bootstrap entire dependency tree underneath it.

what happens if new cacheadaptor(); called inside multiple threads?

for example: thread #1 creates new cacheadaptor via no-arg constructor, , thread #2 same thing. will guice provide same exact widgetcache instance each thread's cacheadaptor, or guice provide 2 different instances each thread? though toinstance(...) supposed return same singleton instance, i'm hoping - since modules created inside 2 distinct threads - each cacheadaptor receive different widgetcache instance.

thanks in advance!

it's not guice will provide same singleton across threads same injector, guice can only provide same singleton across threads if use toinstance. modules evaluated once per injector, , gave guice 1 instance , no way produce second one.

guice isn't magic. when trying provide instance of object, either needs (1) guice-friendly no-arg or @inject-annotated constructor; (2) provider or @provides method, letting create instance yourself; or (3) instance you've created , bound toinstance, guice reuses because doesn't know how create another. note option 2, provider, doesn't need guarantee creates new instance every single time, , can exploit write provider has threadlocal cache. this:

public class cachemodule extends abstractmodule {     /** isn't needed anymore; @provides method below sufficient. */     @override protected void configure() {}      /** keeps widgetcache per thread , knows how create new one. */     private threadlocal<widgetcache> threadwidgetcache = new threadlocal<>() {         @override protected widgetcache initialvalue() {             return new widgetcache(...lots of params);         }     };      /** provide single separate widgetcache each thread. */     @provides widgetcache providewidgetcache() {         return threadwidgetcache.get();     } } 

of course, if want more 1 object, you'd have write threadlocal every single key want cache, , create provider each. seems little excessive, , that's custom scopes come in.

creating own threadlocal scope

check out scope's meaningful method:

/**  * scopes provider. returned provider returns objects scope.  * if object not exist in scope, provider can use given  * unscoped provider retrieve one.  *  * <p>scope implementations encouraged override  * {@link object#tostring} in returned provider , include backing  * provider's {@code tostring()} output.  *  * @param key binding key  * @param unscoped locates instance when 1 doesn't exist in  *  scope.  * @return new provider delegates given unscoped provider  *  when instance of requested object doesn't exist in  *  scope  */ public <t> provider<t> scope(key<t> key, provider<t> unscoped); 

as can see scope interface, scope decorator provider, , scoping thread-local tantamount returning threadlocal-cached copy if exists or caching , returning passed provider if doesn't. can write scope same logic did manually above.

in fact, need create new fooobject per-thread (for value of fooobject) common request—too of "advanced feature" base library, common enough example how write custom scope. adjust simplescope example needs, can leave out scope.enter() , scope.exit() calls, keep threadlocal<map<key<?>, object>> act thread-local cache of objects.

at point, assuming you've created own @threadscoped annotation threadscope implementation you've written, can adjust module this:

public class cachemodule extends abstractmodule {     @override     protected void configure() {         bindscope(threadscoped.class, new threadscope());     }      /** provide single separate widgetcache each thread. */     @provides @threadscoped widgetcache providewidgetcache() {         return new widgetcache(...lots of params);     } } 

remember, singleton behavior doesn't depend on threads create modules in, rather injector you're asking. if created 5 unrelated injector instances, each have own singleton. if you're merely trying run small algorithm in multi-threaded way, create own injector per thread, way you'd lose chance make singleton objects span threads.


Comments

Popular posts from this blog

html - How to style widget with post count different than without post count -

How to remove text and logo OR add Overflow on Android ActionBar using AppCompat on API 8? -

javascript - storing input from prompt in array and displaying the array -