【发布时间】:2014-02-06 09:00:35
【问题描述】:
假设我有 3 个捆绑包 A、B 和 B1。 Bundle A 是我的应用程序的起点。 Bundle B 提供了A 使用的服务的API。 Bundle B1 是服务的实现。
基本上,bundle A 有一组记录,它一个接一个地处理。没有处理记录的顺序。
我想通过同时处理记录子集来提高我的应用程序的性能。
我想到了两种不同的方法:bundle A 的多个实例,以及 bundle A 与多个线程。
AFAIK,不可能在一个 OSGi 容器中添加同一个包的多个实例(即同一个 OSGi 身份)。
关于第二种可能性,bundle A 创建的每个线程都有自己的身份。而B1导出的服务需要知道使用它的线程的身份。因此,我认为ServiceFactoy 适合这里。但是,我已经读过,一旦捆绑获得了服务实例,它就会被缓存。因此,所有线程都会获得相同的服务实例。
我说的对吗?如果是,那么实施该模型的“正确方法”是什么?随意向我推荐一种完全不同的方法,它对 OSGi 更友好。
谢谢, 迈克尔
编辑:
另一种可能性是修改服务接口以允许服务的消费者将他们的身份传递给服务。然后服务将变为“无状态”,并且不需要使用 ServiceFactory。然而,需要标识的事实是一个实现细节(即,仅在这个特定的实现中需要它),因此对于未来的实现,将不会使用添加到接口的参数。这就是我不喜欢触摸界面的原因。
【问题讨论】:
-
“线程的身份”是什么意思?你使用技术吗?如果我是你,我会尝试在新线程中传递相同的身份(猜测设置线程局部变量)。
-
我的意思是在线程创建期间设置了一些硬编码的身份。此身份将用于配置服务实例。使用相同的身份对我没有帮助,因为每个线程应该对返回的服务实例进行不同的配置。
-
您可能对此 RFC 感兴趣:github.com/osgi/design/blob/master/rfcs/rfc0195/… 但是,我认为您仍然应该考虑重构服务,使其能够处理来自多个线程的请求。例如:将自定义工厂注册为服务,而不是注册服务本身。在这种情况下,实例化将掌握在您手中,您可以通过工厂方法的参数传递身份信息。
-
我不反对重构服务。问题是 ServiceFactory 契约明确指出 OSGi 容器将为请求包缓存返回的服务。因此,第一个线程将是触发服务创建的线程,并且将为该线程配置服务实例。但是,其他线程将收到相同的服务实例,这将导致问题。
-
我知道 ServiceFactory 是如何工作的 :)。我的意思是您应该进行一些重构,而不是注册您现在注册的服务,而是将工厂注册为 OSGi 服务。工厂是指您编写的自定义类。客户将获得工厂并在其上调用 getInstance() 方法。如果您使用连接池,那么实现始终实例化您的对象的 createInstance() 函数或应该在 finally 块中调用的 retrieveService 将很重要。
标签: java multithreading osgi