我编写了一个风暴拓扑,并将其工作人员编号设置为1。 所以,我认为它的所有组件都应该在同一个进程中运行。我想在拓扑中的多个组件之间共享一个公共对象,所以我使用单例模式: 1,我在打开独特的喷口时初始化单件对象。 2,然后,我通过调用函数getInstance()来使用其他组件中的单例对象。
但是,我发现我将在不同组件之间获得不同的对象。
感谢您的回复。该问题的关键代码如下: 单例类代码:
public class TraceApplicationContext {
private volatile static TraceApplicationContext instance = new TraceApplicationContext();
private TraceApplicationContext() {
}
public static TraceApplicationContext getInstance() {
return instance;
}
}
SpoutA类代码:
public class SpoutA extends BaseRichSpout {
public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
TraceApplicationContext.getInstance().init();
}
}
BoltA代码:
public class BoltA extends BaseRichBolt {
private static JedisCluster jedisCluster = TraceApplicationContext.getInstance().getJedisCluster();
}
BoltB代码:
public class BoltB extends BaseRichBolt {
private static JedisCluster jedisCluster = TraceApplicationContext.getInstance().getJedisCluster();
}
在SpoutA中初始化了TraceApplicationContext单例对象后,我通过TraceApplicationContext.getInstance()。getJedisCluster()检查对象返回,它不是null。但我在BoltA和BoltB中检查它,TraceApplicationContext.getInstance()返回的对象.getJedisCluster()为空。
有没有人遇到过同样的问题,或者知道这个问题有什么问题?
请帮忙! 谢谢!
答案 0 :(得分:3)
如果你不能使用枚举,因为@Jorge_B说你可以在getInstance()
方法中使用同步块
public class MySingleton {
private static volatile MySingleton instance;
private MySingleton() { ... }
public static MySingleton getInstance() {
if (instance == null) {
synchronized(MySingleton.class) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}
}
http://en.wikipedia.org/wiki/Singleton_pattern
编辑
但这可能不是单身人士的问题
getJedisCluster()
返回不同值的事实并不意味着它不是单一的单身,而是单身人士的状态发生了变化
尝试在单例内设置jedisCluster
final(最终属性无法更改,但必须在构造函数内初始化)
private final JedisCluster jedisCluster;
如果您无法尝试跟踪jedisCluster的更改时间:使用setter ......
答案 1 :(得分:1)
如果您确保所有进程都在同一个JVM中运行,请尝试将Singleton实现为单个元素的Enumeration
。这应该解决对象初始化的每个可能的并发问题。
例如:
像
这样的实现public class MySingleton {
private static MySingleton instance;
private MySingleton() { ... }
public static MySingleton getInstance() {
if (instance == null) { instance = new MySingleton() }
return instance;
}
}
容易出现并发问题。但是,像这样的人
public enum MySingleton {
INSTANCE;
private MySingleton() {...}
}
应该无处不在。
答案 2 :(得分:0)
根据我的经验,我使用单独的cassandra会话对象,以及我的风暴拓扑中的应用程序属性的单例。 由于这些单例对象没有任何变化状态,即使我们有多个WorkerProcess(WP)(即每个WP一个JVM),每个WP都会有一个单例的副本,可以毫无问题地使用。
就最佳实践而言,最好在提交拓扑时将静态单例设置为配置对象,并且prepare方法将其提供给各个任务。
https://groups.google.com/forum/#!topic/storm-user/rWeQpGEnT9Q