Git Product home page Git Product logo

guice-util's Introduction

Guice-Util

Additional Guice scoping machinery. Javadoc here.

My original blog post explains the motivation. I've reproduced it here, as well.

Original post

William Pietri asked whether it would be possible to take advantage of concurrency and Guice's knowledge of dependencies to provide interdependent (and expensive to create) singleton services in parallel.

For example, say that service A depends on services B and C and that B and C don't know about each other (and so could be constructed concurrently). Obviously, you could explicitly construct B and C in separate tasks running in a thread pool, then construct A once B and C exist.

class A {
    A(B b, C c) { /* ... use b and c ... */ }
}

class B {
    B() { /* ... takes a long time ... */ }
}

class C {
    C() { /* ... takes a long time ... */ }
}

class Services {
    A a; B b; C c;
    void init() throws InterruptedException {
        final CountDownLatch ready = new CountDownLatch(2);
        Executor pool = Executors.newCachedThreadPool();
        pool.execute(new Runnable() {
            public void run() { b = new B(); ready.countDown(); }
        })
        pool.execute(new Runnable() {
            public void run() { c = new C(); ready.countDown(); }
        })
        ready.await();
        a = new A(b, c);
        // Now publish a, b, and c safely -- not shown.
    }
}

But it's a pain to have to orchestrate this yourself. You have to know the dependencies intimately and write a lot of tricky code. If the dependencies change, the code has to be completely rethought. Wouldn't it be nice if Guice could do this for you automatically without giving up on the opportunities for concurrency? Well, it turns out that it can.

The idea is to use a variant of singleton scope that runs the providers of all bindings for that scope in separate threads. Naturally some of these providers block in their own thread while their dependencies finish in other threads, but those services that can be constructed in parallel will be.

Here's what the Guice version looks like:

@ConcurrentSingleton
class A {
    @Inject A(B b, C c) { /* ... use b and c ... */ }
}

@ConcurrentSingleton
class B {
    @Inject B() { /* ... takes a long time ... */ }
}

@ConcurrentSingleton
class C {
    @Inject C() { /* ... takes a long time ... */ }
}

No special initialization code needed, just inject A, B, and C wherever they are needed. (Note that if you have circular dependencies, this probably won't work. So don't have circular dependencies.)

ConcurrentSingleton is just a scope annotation. The actual scope implementation is ConcurrentSingletonScope. I have a fleshed-out version of the A, B, C example, ConcurrentSingletonExample, that is slightly different from the code above; it uses Providers for B and C so that A can do some work before getting B and C in the constructor.

You aren't forced to do all the expensive work in the constructor. You could also inject a start method with injected parameters to provide needed dependencies.

In the same thread that provoked the ConcurrentSingleton response, Jesse Wilson suggested the use of the experimental lifecycle facility in Guava. This could prove useful in the current context if, for example, you have singleton services that take a while to stop and could benefit from being stopped in parallel.

Update 2009-11-30

I added a call to pool.shutdown() in the scope implementation to make sure the pool threads don't prevent the JVM from exiting. It might not be necessary, but I don't think it hurts.

Update 2010-7-3

Added explicit notice that the sources are in the public domain.

Update 2018-10-16

Added a GitHub repository with the concurrent singleton code and other utilities, as the old links to code weren't working any more. Now using MIT open source license.

guice-util's People

Contributors

tembrel avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.