2013-09-22 4 views
6

У меня есть класс одноплодный:переменного экземпляра в классе Singleton доступа к нескольким потокам

public class School { 
    private HashMap<String, String> students; 

    private static School school; 

    private School(){ 
     students = new HashMap<String, String>(); 
    } 

    public static School getInstance(){ 
     if(school == null){ 
      school = new School(); 
     } 
     return school; 
    } 

    //Method to add student 
    protected void addStudent(String id, String name){ 
      students.put(id,name); 
    } 
    //Method to remove student 
    protected void removeStudent(String id){ 
      students.remove(id); 
    } 
} 

Как вы можете видеть выше, в классе одноплодного, у меня есть students переменного (а HashMap), есть способы для добавления & удалить ученика в классе.

В моем приложении может быть несколько потоков, используя этот класс School до getInstance(), а затем добавив & удаление ученика. Для того, чтобы сделать доступ (особенно доступ кstudentsнапример) быть поточно, я имею в виду использовать synchorized ключевое слово для getInstanc() метода, как:

public synchronized static School getInstance(){ 
     if(school == null){ 
      school = new School(); 
     } 
     return school; 
    } 

Но я думаю, что мое тривиальное изменение может только убедитесь, что только одинSchool экземпляр создается в многопоточной среде. Что еще мне нужно сделать, чтобы сделать это потокобезопасным для доступа кstudentsэкземпляр несколькими потоками также. Любое хорошее предложение или комментарий оспаривается, спасибо!

+1

Читать это: http://stackoverflow.com/questions/11165852/java-singleton-and-synchronization –

+0

Требуется ли ленивая инициализация? – chrylis

+0

Да, ленивая инициализация - это требование – Mellon

ответ

3

Оставив разговор о том одиночки злы или нет, давайте рассмотрим только вопросы безопасности нити в вашем School классе:

  • Общий объект создается «ленивым» - это требует синхронизации, чтобы избежать получений два экземпляра School; вы правильно определили и исправили эту проблему. Однако, поскольку инициализация School не занимает много времени, вы можете также сделать getInstance() тривиальным получателем, инициализируя school = new School() с нетерпением.
  • Хэш-карта внутри школы - одновременный доступ к карте хеша приведет к исключениям. Вам нужно добавить синхронизацию вокруг кода, который добавляет, удаляет и итерации студентов, чтобы избежать этих исключений.
  • Доступ к отдельным студентам - после того, как абоненты получат объект Student, они могут начать изменять его одновременно. Поэтому объект Student нуждается в собственной параллельной защите.
+0

Привет, для каждого учащегося, каждому потоку нужно только получить доступ к методу getter (например, getStudentName()), является ли ваш третий вопрос по-прежнему проблемой? – Mellon

+0

@Mellon Если ваши потоки только получают свойства 'Student', но не устанавливают их, тогда вам не нужна синхронизация. – dasblinkenlight

0

Реализация HashMap не является потокобезопасной, поэтому могут произойти плохие вещи, если несколько потоков работают на ней в одно и то же время. Быстрое исправление making the map itself synchronized:

students = Collections.synchronizedMap(new HashMap<String, String>()); 

Обратите внимание, что если вы итерацию на этой карте, итерация также должно быть сделано в synchronized блоке; иначе другие потоки могут изменять карту во время итерации.

Нить-безопасная альтернатива HashMap является ConcurrentHashMap

0

метод Synchronizing делает их поточно это означает, что только один поток может выполнять этот метод в то время.

Однако в приведенной выше ситуации я бы предложил синхронизировать метод addStudent и removeStudent. Или вы можете синхронизировать хэш-карту учащихся также используя -

Collections.synchronizedMap (новый HashMap());

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