2013-11-29 3 views
0

У меня есть простой класс, который выполняет некоторые проверки снова список шаблонов Regex. Мои шаблоны задаются каким-то образом с постоянным списком значений. На данный момент это не вопрос, поэтому я опускаю этот код настройки.Spring scope = `prototype`: как изменить все экземпляры bean?

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 одновременных потоков. Класс создается с весовой шкалой по умолчанию 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; 
    } 
    } 
} 

Ну, так как все потоки получают доступ к одному экземпляру моего класса - они блокируются внутри синхронизированного блока. Поскольку мой класс довольно легкий, я хотел бы создать отдельный экземпляр для каждого потока (например, сменить область от 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. Но есть ли еще какой-нибудь другой способ сделать это?

+1

Мне сложно понять, что вы пытаетесь выполнить. Является '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' Если это так, не будет использовать прототип bean победить цель? Объекты 'Pattern' являются потокобезопасными, поэтому кажется, что имеет смысл просто использовать поточно-безопасную коллекцию и удалять синхронизацию на' check'. – chrylis

+0

Да. Мой вопрос заключался в том, как динамически изменять «шаблоны» во всех экземплярах «прототипа»;) – Archer

+0

По-прежнему не понимаю, почему вы в первую очередь сделали 'check'' synchronized'. – chrylis

ответ

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; 
    } 
} 
+0

Спасибо. Я попробую ваше предложение сейчас. – Archer

Смежные вопросы