假设我有一个类:
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使用为注入,并使用为注入,然后用于创建和执行它所传递的实例。由于它是一个缓存池,因此只有在需要但不可用时才创建新线程。
我想知道当我们将作为单例或非单例注入时,Guice在多线程环境下会如何“表现”。
让我们从非单例开始:
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将注入为单例,我认为每个线程都有其自己的注入副本,因此我们不必添加任何类似于synchronize
的代码来防止3个发生冲突并导致线程问题。
但是当我们让Guice将注入为单例时会发生什么?!? 现在,在MyAppModule
中:
@Provides @Singleton
FizzImpl providesFizz() {
return new FizzImpl(true, Buzz.ALWAYS, 35);
}
如果Guice只提供
FizzImpl
的1个全局单例实例,那么在3个衍生线程中每个线程内部的FizzImpl
"副本"(如果这是正确的词)会产生什么后果?需要注意哪些陷阱?有哪些避免这些陷阱的方法?谢谢。
@Singleton
,那么你将有三个引用指向同一个对象。我不确定这其中有什么让人惊讶或与未使用依赖注入时的情况不同之处。 - Louis WassermanFizzImpl
是线程安全的,对吗? - IAmYourFaja