繁体   English   中英

Guice如何将单例和非单例注入多个线程

[英]How Guice injects singletons and non-singletons into multiple threads

说我有一节课:

public class MyTask implements Runnable {
    @Inject
    private Fizz fizz;

    // Getters and setters for 'fizz'.

    @Override
    public void run() {
        if(fizz.alleviatesBuzz())
            doA();
        else
            doB();
    }

    private void doA() { ... }

    private void doB() { ... }
}

然后我又上了一堂课:

public class MyTaskDispatcher {
    @Inject
    private ThreadFactory threadFactory;

    private Executor executor;

    // Getter and setter for 'threadFactory'.

    public void dispatch(MyTask task) {
        if(executor == null)
            executor = Executors.newCachedThreadPool(threadFactory);

        executor.submit(task);
    }
}

所以Guice用Fizz注入了MyTask ,并且还为MyTaskDispatcher注入了一个ThreadFactory ,然后用于创建和执行它传递的MyTask实例。 而且,由于它是一个缓存池,它只在需要一个新线程时创建一个新线程但不可用。

我想知道当我们将Fizz作为单例或非单例注入时,Guice如何在多线程环境中“表现”。

让我们从非单例for-instance开始:

public class MyAppModule extends AbstractModule {
    @Override
    public void configure() {
        bind(Fizz.class).to(FizzImpl.class);

        // I don't think the functionality of MyThreadFactory
        // really matters for the sake of this question.
        bind(ThreadFactory.class).to(MyThreadFactory.class);
    }

    @Provides
    FizzImpl providesFizz() {
        return new FizzImpl(true, Buzz.ALWAYS, 35);
    }

    // I *believe* we always want the ThreadFactory to be singleton,
    // because all of the threads spawn from it and its executor.
    @Provides @Singleton
    ThreadFactory providesThreadFactory() {
        return new MyThreadFactory(12);
    }
}

现在让我们说应用程序已经运行了一段时间,并且已经提交了3个单独的MyTask ,因此存在3个正在运行的线程。 由于我们没有要求Guice将Fizz es作为单例注入,我假设每个线程都有自己的注入FizzImpl的副本,我们不必添加任何synchronize类型的代码来防止3 FizzImpl的冲突和导致线程问题。

但是当我们让Guice将FizzImpl注入单身时会发生什么?!? 现在,在MyAppModule

    @Provides @Singleton
    FizzImpl providesFizz() {
        return new FizzImpl(true, Buzz.ALWAYS, 35);
    }

如果Guice只提供1个FizzImpl全局单例实例,那么FizzImpl “副本”的下游分支(如果这是正确的话)在3个衍生线程中的每一个内部是什么? 有什么值得注意的陷阱? 有什么方法可以解决这些陷阱? 提前致谢。

不,Fizz将使用MyTask实例创建,它将持续存在多个线程调用。 如果你想为每个线程都有一个Fizz副本,你必须以懒惰的方式进行。

public class MyTask implements Runnable {
    @Inject
    private Provider<Fizz> fizzProvider;

    // Getters and setters for 'fizz'.

    @Override
    public void run() {
        Fizz fizz = fizzProvider.get();
        if(fizz.alleviatesBuzz())
            doA();
        else
            doB();
    }

    private void doA() { ... }

    private void doB() { ... }
}

但是如果你将一个Singleton标志放到Fizz绑定中,那么当你调用fizzProvider.get()时,提供程序将返回相同的实例,因此所有线程都将具有相同的实例。 你必须保持非单身。

你的模块也是错误的,你应该使用方法或隐式绑定,而不是两者。 你也不能提供实例并注入它的界面。

public class MyAppModule extends AbstractModule {
    @Override
    public void configure() {
        bind(Fizz.class).to(FizzImpl.class);
        //or bind(Fizz.class).toInstance(new FizzImpl(true, Buzz.ALWAYS, 35)); //Singleton!!
        //or bind(Fizz.class).toProvider(new Provider<Fizz>() {
        //      @Override
        //      public Subject get() {
        //        return new FizzImpl(true, Buzz.ALWAYS, 35);
        //      }
        //    });

        // I don't think the functionality of MyThreadFactory
        // really matters for the sake of this question.
        bind(ThreadFactory.class).to(MyThreadFactory.class);
    }
}

要么

public class MyAppModule extends AbstractModule {
    @Override
    public void configure() {
    }

    @Provides
    Fizz providesFizz() {
        return new FizzImpl(true, Buzz.ALWAYS, 35);
    }

    // I *believe* we always want the ThreadFactory to be singleton,
    // because all of the threads spawn from it and its executor.
    @Provides @Singleton
    ThreadFactory providesThreadFactory() {
        return new MyThreadFactory(12);
    }
}

希望它会有所帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM