我对Guice以及它的单例是否服从线程限制(我可以尝试设置)感到担忧:
public class CacheModule extends AbstractModule {
@Override
protected void configure() {
// WidgetCache.class is located inside a 3rd party JAR that I
// don't have the ability to modify.
WidgetCache widgetCache = new WidgetCache(...lots of params);
// Guice will reuse the same WidgetCache instance over and over across
// multiple calls to Injector#getInstance(WidgetCache.class);
bind(WidgetCache.class).toInstance(widgetCache);
}
}
// CacheAdaptor is the "root" of my dependency tree. All other objects
// are created from 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.
}
如您所见,每次我们创建的新实例时CacheAdaptor
,CacheModule
都会使用a来引导其下的整个依赖关系树。
如果new CacheAdaptor();
从多个线程内部调用会怎样?
例如:线程1 CacheAdaptor
通过其no-arg构造函数创建了一个新线程,而线程2执行了相同的操作。
Guice将为WidgetCache
每个线程的实例提供相同的确切实例CacheAdaptor
,还是Guice将为每个线程提供2个不同的实例?尽管toInstance(...)
应该返回相同的单例实例,但我希望-
由于模块是在2个不同的线程内创建的-每个模块都CacheAdaptor
将接收不同的WidgetCache
实例。
提前致谢!
Guice不仅 会 为同一注射器提供相同的单线程跨线程,而且如果您使用,Guice 只能
提供相同的单线程跨线程toInstance
。每个进样器对模块进行一次评估,您给了Guice一个实例,而没有办法再生产第二个。
Guice不是魔术。尝试提供Object的实例时,它要么需要(1)一个Guice友好的无参数或带有@Inject
注释的构造函数;(2)Provider
或@Provides
方法,让您自己创建实例;或(3)您已经创建并与绑定的实例,toInstance
Guice重用了它,因为它不知道如何创建另一个实例。请注意,带有的选项2
Provider
并不需要保证每次都创建一个新实例,我们可以利用它来编写Provider
具有ThreadLocal缓存的。它看起来像这样:
public class CacheModule extends AbstractModule {
/** This isn't needed anymore; the @Provides method below is sufficient. */
@Override protected void configure() {}
/** This keeps a WidgetCache per thread and knows how to create a new one. */
private ThreadLocal<WidgetCache> threadWidgetCache = new ThreadLocal<>() {
@Override protected WidgetCache initialValue() {
return new WidgetCache(...lots of params);
}
};
/** Provide a single separate WidgetCache for each thread. */
@Provides WidgetCache provideWidgetCache() {
return threadWidgetCache.get();
}
}
当然,如果要对多个对象执行此操作,则必须为要缓存的每个键编写一个ThreadLocal,然后为每个键创建一个提供html" target="_blank">程序。这似乎有点多余,这就是自定义作用域引入的地方。
查看Scope唯一有意义的方法:
/**
* Scopes a provider. The returned provider returns objects from this scope.
* If an object does not exist in this scope, the provider can use the given
* unscoped provider to retrieve one.
*
* <p>Scope implementations are strongly encouraged to override
* {@link Object#toString} in the returned provider and include the backing
* provider's {@code toString()} output.
*
* @param key binding key
* @param unscoped locates an instance when one doesn't already exist in this
* scope.
* @return a new provider which only delegates to the given unscoped provider
* when an instance of the requested object doesn't already exist in this
* scope
*/
public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped);
从Scope接口可以看到,作用域只是的装饰器,对Provider
局部线程进行范围界定无异于返回ThreadLocal
-cached副本(如果存在)或缓存并从传递的副本返回(Provider
如果不存在)。因此,我们可以轻松地编写一个作用域,该作用域执行与上面手动执行的逻辑相同的操作。
实际上,需要为每个线程(对于FooObject的任何值)创建一个新的FooObject是一个常见的请求-
对于基础库来说,这是“高级功能”的太多内容,但是足以作为示例说明如何编写自定义范围。要根据需要调整该SimpleScope示例,可以省略scope.enter()
和scope.exit()
调用,但保留ThreadLocal<Map<Key<?>, Object>>
用作对象的线程本地缓存。
到那时,假设您已经@ThreadScoped
使用ThreadScope
编写的实现创建了自己的注释,则可以将模块调整为如下所示:
public class CacheModule extends AbstractModule {
@Override
protected void configure() {
bindScope(ThreadScoped.class, new ThreadScope());
}
/** Provide a single separate WidgetCache for each thread. */
@Provides @ThreadScoped WidgetCache provideWidgetCache() {
return new WidgetCache(...lots of params);
}
}
记住,单例行为并不取决于您在哪个线程中创建模块,而是取决于您要问的是哪个注入器。如果创建了五个不相关的Injector
实例,则每个实例将具有自己的单例。如果您只是尝试以多线程方式运行小型算法,则可以为每个线程创建自己的注入器,但是那样您将失去创建跨线程的单例对象的机会。
问题内容: 如何使用go编程语言实现Singleton设计模式? 问题答案: 撇开是否实现单例模式的观点不谈,以下是一个可能的实现: 并且是私人的,但是公开的。因此,你不能直接实例没有经历,和它跟踪实例的数量与私人布尔。调整口味的定义。 但是,正如其他几个人指出的那样,这不是线程安全的,除非您仅在中初始化单例。更好的方法是利用您的辛勤工作: 另请参见,hasan j的建议只是将包 视为 单例。最后
Singleton的目的是控制对象创建,将对象数量限制为只有一个。 由于只有一个Singleton实例,Singleton的任何实例字段每个类只会出现一次,就像静态字段一样。 单身人士通常控制对资源的访问,例如数据库连接或套接字。 例如,如果您的数据库只有一个连接的许可证,或者您的JDBC驱动程序遇到多线程问题,则Singleton会确保只建立一个连接,或者一次只能有一个线程访问该连接。 实施单身
我正在做一个项目,其中我有一个节点之间的距离矩阵,我导入到cplex。我这样做: 它导入所有内容,但当我添加限制时,距离矩阵不受尊重,变量显示没有连接的节点之间的连接。另外,最后的限制改变了q的值,为什么会发生这种情况?我怎样才能解决这个问题? 提前谢谢。 目标函数和限制条件如下:
问题内容: 我需要测试一些遗留代码,该遗留代码在方法调用中使用单例。该测试的目的是确保clas sunder测试调用单例方法。我在SO上也看到过类似的问题,但是所有答案都需要其他依赖项(不同的测试框架)-不幸的是,我仅限于使用Mockito和JUnit,但这在如此流行的框架下应该是完全可能的。 单例: 被测课程: 单元测试: 这个想法是配置可怕的单例的预期行为,因为被测类将调用它的getInsta
我有以下JPA实体 这是我检查唯一约束的测试,插入具有相同电子邮件的另一个用户。
问题内容: 我想启动许多要在+ -42Mio记录的数据库上运行的任务。我想批量运行5000条记录/时间(结果是850个任务)。我还想将线程数限制为16个,因此Java开始为我执行此操作,并且我正在使用当前代码来完成此任务: 这是正确的方法吗?特别是当我有一种印象,即Java会触发所有任务…(实现) 问题答案: 使用ExecutorService的第一部分看起来不错: 带有Thread的部分不应该在