风暴拓扑中的单一模式

时间:2015-05-06 08:55:23

标签: java singleton apache-storm

我编写了一个风暴拓扑,并将其工作人员编号设置为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()为空。

有没有人遇到过同样的问题,或者知道这个问题有什么问题?

请帮忙! 谢谢!

3 个答案:

答案 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