java - 在线程安全类中返回一个对象

标签 java concurrency thread-safety

我遇到的问题似乎表明 Java 对象没有在我预期的堆上创建。简短的版本是我有一个 JMS onMessage() 方法,它调用另一个方法来根据 TextMessage 的 JSon 有效负载实例化适当的对象 (routingCommand)。

    public void onMessage(Message message) throws RuntimeException {

IRoutingCommand routingCommand = null;
routingCommand = instantiateRoutingCommand(message);
...
process(routingCommand);
}

private IRoutingCommand instantiateRoutingCommand(Message message)  {

    IRoutingCommand routingCommand = null;

    ... lots of code to build the correct type of RoutingCommand

    routingCommand = new IeRoutingCommand(ieNotification);
    return routingCommand;
}

问题是在我的负载测试期间,在极其罕见的情况下,同一个 JMS 消息被“process()ed”多次。当我设置 maxConcurrentConsumers=1 时,这不会发生。

我在 Internet 上发现了这个我从来不知道的智慧 gem ,但假设它是正确的,它就可以解释我的问题:

对象的本地引用有点不同。引用本身不共享。然而,引用的对象并不存储在每个线程的本地堆栈中。所有对象都存储在共享堆中。

instantiateRoutingCommand 方法大约有 50 行长——这就是为什么我一开始就把它拆开的原因。我可以充分检查 JMS 消息以确定它代表什么类型的对象并在 onMessage() 方法中实例化它并将 instantiateRoutingCommand 转换为仅在传递的对象上使用 setter。这样就满足了上面的规定。但即便如此,这也不是完全微不足道的,并且会使 onMessage() 方法变得困惑。

我没有尝试使对象易变或使任何东西同步,因为如果上述情况属实,那么我看不到任何帮助。那么在多线程对象中处理传递对象的最佳方式是什么?

最佳答案

您必须同步访问多个线程引用的对象,或者为每个线程提供自己的副本。虽然后者可能是唯一有效的解决方案,但应注意复制的对象不包含被复制对象中也包含的引用。

关于java - 在线程安全类中返回一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18880502/

相关文章:

java - 同步和可见性

Java awt 字体间距选项

Java - 确切含义http.maxConnections

java - 用于学习 Java 中的内存模型和线程安全的资源

java - Java 日历操作的结果不一致

java - Spring 对象池和线程阻塞

java - 针对经验丰富的 Flash 开发人员的实际 Java 初学者教程

java - 在Jhipster中使用JDL时出错

java - 在同一 Activity android上使用前后摄像头

java - JButton 不工作[捕获网络流量]