From: Andy Heninger Date: Fri, 25 Apr 2014 19:58:47 +0000 (+0000) Subject: ICU-10767 Use ConcurrentHashMap with RuleBasedBreakIterator. X-Git-Tag: milestone-59-0-1~1940 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=db886fc4b2f60bb5505815a9bafc7fd8062e99c7;p=icu ICU-10767 Use ConcurrentHashMap with RuleBasedBreakIterator. X-SVN-Rev: 35656 --- diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/RuleBasedBreakIterator.java b/icu4j/main/classes/core/src/com/ibm/icu/text/RuleBasedBreakIterator.java index 9242f882c58..c317846f1ae 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/RuleBasedBreakIterator.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/RuleBasedBreakIterator.java @@ -17,9 +17,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.CharacterIterator; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import com.ibm.icu.impl.Assert; import com.ibm.icu.impl.CharTrie; @@ -251,8 +249,8 @@ public class RuleBasedBreakIterator extends BreakIterator { private int fPositionInCache; - private final Map fBreakEngines = - Collections.synchronizedMap(new HashMap()); + private final ConcurrentHashMap fBreakEngines = + new ConcurrentHashMap(); /** * Dumps caches and performs other actions associated with a complete change * in text or iteration position. @@ -1064,11 +1062,9 @@ public class RuleBasedBreakIterator extends BreakIterator { // We have a dictionary character. // Does an already instantiated break engine handle it? - synchronized(fBreakEngines) { - for (LanguageBreakEngine candidate : fBreakEngines.values()) { - if (candidate.handles(c, fBreakType)) { - return candidate; - } + for (LanguageBreakEngine candidate : fBreakEngines.values()) { + if (candidate.handles(c, fBreakType)) { + return candidate; } } @@ -1125,12 +1121,13 @@ public class RuleBasedBreakIterator extends BreakIterator { } if (eng != null && eng != fUnhandledBreakEngine) { - fBreakEngines.put(script, eng); + LanguageBreakEngine existingEngine = fBreakEngines.putIfAbsent(script, eng); + if (existingEngine != null) { + // There was a race & another thread was first to register an engine for this script. + // Use theirs and discard the one we just created. + eng = existingEngine; + } // assert eng.handles(c, fBreakType); - - // In the event of a race it's possible that the add() could fail - // and that two break engines of the same type will exist. - // Should be rare and pretty much harmless. } return eng; }