我是一个简单的类,它执行一些Regex模式的再次检查列表。我的模式以某种方式设置了常量值列表。这不是现在的问题,所以我省略了设置代码。
class Checker {
private final Pattern [] patterns = new Pattern[10];
public boolean check(final String param){
for(Pattern p : patterns){
if(p.matcher(param).matches())
return true;
}
return false;
}
}
东西很简单。
现在我从500个同步线程访问该类。使用默认的Spring范围singleton
创建类。
访问patterns
同步:
class Checker {
private final Pattern [] patterns = new Pattern[10];
public boolean check(final String param){
synchronized(patterns){
for(Pattern p : patterns){
if(p.matcher(param).matches())
return true;
}
return false;
}
}
}
好吧,因为所有线程都访问我的类的单个实例 - 它们被锁定在synchronized块中。由于我的课程相当轻量级,我想为每个帖子创建单独的实例(例如,将范围从singleton
更改为prototype
)。删除同步块并添加getInstance
支持的ThreadLocal
工厂方法。像那样:
class Checker {
private final Pattern [] patterns = new Pattern[10];
public boolean check(final String param){
for(Pattern p : patterns){
if(p.matcher(param).matches())
return true;
}
return false;
}
private static final ThreadLocal<Checker> checkerLocal =
new ThreadLocal<Checker>() {
@Override
protected Checker initialValue() {
System.out.println("Creating Checker instance")
return new Checker();
}
};
public static Checker getInstance(){
return checkerLocal.get();
}
}
像魅力一样。
但是,想象一下我动态以某种方式在我的应用程序中修改模式(例如在那里添加或删除模式)。我应该为Checker
类的所有现有实例执行该操作。
我正在考虑使用ApplicationContext#getBeansOfType(Checker.class)
方法来获取所有bean实例。但还有其他更多的springy
方式吗?
答案 0 :(得分:1)
这是我的建议。 Checker
类根本不需要任何同步,因为它只从持有者类中提取不可修改的List<Pattern>
,并且所需的唯一同步是防止持有者发生冲突更新。
public class PatternService {
AtomicReference<List<Pattern>> patterns = new AtomicReference<>(Collections.emptyList());
public List<Pattern> getPatterns() {
return patterns.get();
}
public synchronized void addPattern(Pattern p) {
List<Pattern> newPatterns = new LinkedList<>(patterns.get());
newPatterns.add(p);
patterns.set(Collections.unmodifiableList(newPatterns)); // or ImmutableList
}
// other mutators
}
public class Checker {
@Autowired PatternService patternService;
public boolean check(String param) {
for(Pattern p: patternService.getPatterns())
if(p.matcher(param).matches())
return true;
return false;
}
}