我有一个简单的类,它对正则表达式模式列表执行一些检查。我的模式是通过恒定的值列表以某种方式设置的。目前这不是一个问题,所以我省略了该设置代码。
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
创建的。
同步访问模式
:
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 block)中。由于我的类相当轻量级,我想为每个线程创建单独的实例(例如,将范围从 singleton
更改为 prototype
)。删除同步块(synchronized block)并添加由 ThreadLocal
支持的 getInstance
工厂方法。像这样:
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 实例。但是还有其他更有弹性的方法吗?
最佳答案
这是我的建议。 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;
}
}
关于java - Spring 范围 =`prototype` : how to change all bean instances?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20288494/