2015-08-13 45 views
2

在我的应用程序中,我有一个同时由多个线程调用的方法。每个线程在运行时多次调用此方法。如何在多线程应用程序中使用Locale来提高性能

private Locale trLoc = new Locale("tr", "TR"); 

public double calculate(String arg1){ 
    arg1 = arg1.toUpperCase(trLoc); 
... 
} 

该方法使得一个String.toUpperString(区域)呼叫导致因为Locale类内哈希表的使用的一个瓶颈。每个线程在toUpperCase方法运行时等待另一个线程。这种情况使我的应用程序减慢了三倍。

有什么我失踪的地方使用或我必须使用另一个类为同一目的吗?

在此先感谢。

回答

3

经过短暂的探索,它看起来像JDK不能帮助你。我建议获得java.lang.ConditionalSpecialCasing类,复制它并修复Hashtable的问题。您可以用HashMap代替Hashtable。我没有看到在这里使用Hashtable的任何理由。

+0

我很惊讶这样的“功能”之前没有被检测到。我在Google上处理与'ConditionalSpecialCasing'相关的性能问题,结果什么都没有。 –

+1

它只发生在(java.lang.String) 'boolean localeDependent =(lang ==“tr”|| lang ==“az”|| lang ==“lt”);' – sibnick

+0

它可能是值得报告的这[对Oracle](http://bugreport.java.com) - 我会这样做,但我认为如果RFE是由实际遇到问题并可以提供测试用例的人提交,那将是最好的。 –

3

编辑:解决方案波纹管实际上不会工作,因为java.lang.ConditionalSpecialCasing类中有问题的HashTable是静态的,仍然会被所有线程共享。我建议你接受sibnick的回答而不是我的回答。


一个简单的解决办法是让trLoc一个ThreadLocal:一个新的实例会为每个线程自动创建(如需要)。如果你有一个线程池或者类似的话,这将工作得很好:你只会创建与你的池中的线程一样多的Locale实例,这应该是非常合理的。由于每个线程都将访问不同的实例Locale,因此不再有争用访问同步的HashTable。

private ThreadLocal<Locale> trLoc = new ThreadLocal<Locale>() { 
    @Override 
    protected Locale initialValue() { 
     return new Locale("tr", "TR"); 
    } 
}; 

public double calculate(String arg1){ 
    arg1 = arg1.toUpperCase(trLoc.get()); 
    ... 
} 
+0

这不起作用。 'ConditionalSpecialCasing'在内部仍然使用相同的'Hashtable',不管你创建了多少'Locale'。 –

+0

检查完代码后,它看起来像是对的 - HashTable是静态的,并且将始终由所有线程共享...我编辑了我的答案。 –