Скажем, у меня есть класс:Как Guice впрыскивает одиночек и не-одиночек в несколько потоков
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 впрыскивает MyTask
с Fizz
, и также вводит MyTaskDispatcher
с ThreadFactory
, который затем используется для создания и выполнения MyTask
экземпляров, которые передаются. И, поскольку это кешированный пул, он создает новый поток только тогда, когда он нужен, но недоступен.
Мне интересно, как Guice «ведет себя» в многопоточной среде, когда мы вводим Fizz
в качестве одноэлементного или неэлементного.
Давайте начнем с не-синглтон для-например:
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 как singleton, я предполагаю, что каждый поток имеет свою собственную копию введенного FizzImpl
, и нам не нужно добавлять какой-либо код synchronize
, чтобы предотвратить столкновение 3 FizzImpl
s и вызывая проблемы с потоком.
Но что происходит, когда мы делаем инъекцию Guice FizzImpl
в качестве одноэлементного?!? Теперь в MyAppModule
:
@Provides @Singleton
FizzImpl providesFizz() {
return new FizzImpl(true, Buzz.ALWAYS, 35);
}
Если Guice только обеспечивает 1 глобальной, одноплодную экземпляр FizzImpl
, какова нисходящие последствия этого FizzImpl
«копировать» (если это правильное слово для этого) внутри каждый из 3 порожденных нити? Каковы подводные камни, на которые нужно следить? Каковы способы борьбы с этими подводными камнями? Заранее спасибо.
Если вы вводите '@ Singleton', то у вас будет три ссылки на один и тот же объект. Я не уверен, что это удивительно или отличается от того, что произойдет, если вы не используете DI. –
Спасибо @Louis Wasserman (+1) - так что в этом случае я должен был убедиться, что singleton 'FizzImpl' был потокобезопасным, да? – IAmYourFaja
Абсолютно. Это справедливо для любого объекта, на который ссылаются несколько потоков. –