Java 1.4 синглтон, содержащий изменяемое поле - PullRequest
2 голосов
/ 16 марта 2010

Я работаю над унаследованным проектом Java 1.4, и у меня есть фабрика, которая создает экземпляр синтаксического анализатора файла csv в качестве одиночного.

Однако в моем анализаторе CSV-файлов у меня есть HashSet, в котором будут храниться объекты, созданные из каждой строки моего CSV-файла. Все это будет использоваться веб-приложением, и пользователи будут загружать файлы CSV, возможно одновременно.

Теперь мой вопрос: каков наилучший способ предотвратить изменение моего списка объектов двумя пользователями?

Пока что я делаю следующее:

final class MyParser {
    private File csvFile = null;
    private Set myObjects = Collections.synchronizedSet(new HashSet);

    public synchronized void setFile(File file) {
        this.csvFile = file;
    }

    public void parse()
        FileReader fr = null;
        try {
            fr = new FileReader(csvFile);
            synchronized(myObjects) {
                myObjects.clear();
                while(...) { // foreach line of my CSV, create a "MyObject"
                    myObjects.add(new MyObject(...));
                }
            }
        } catch (Exception e) {
          //...
        }
    }    
}    

Должен ли я оставить блокировку только в наборе myObjects или объявить весь метод parse () как синхронизированный?

Кроме того, как я должен синхронизировать - оба - настройки csvFile и синтаксического анализа? Я чувствую, что мой реальный дизайн не работает, потому что потоки могут изменить файл csv несколько раз, пока выполняется, возможно, длительный процесс синтаксического анализа.

Надеюсь, я достаточно ясен, потому что сам немного запутался в этих проблемах мультисинхронизации.

Спасибо; -)

Ответы [ 4 ]

3 голосов
/ 16 марта 2010

По сути, вы предполагаете, что методам необходимо сначала установить setFile, а затем вызвать синтаксический анализатор. Давайте рассмотрим это, t1 (с setFile XX) и t2 (с setFile YY) идут одновременно, а t2 устанавливает для файла значение YY. Затем t1 запрашивает parse () и начинает получать записи от YY. Никакое количество синхронизированных не решит это за вас, и единственный выход состоит в том, чтобы метод parse принял параметр File или удалил одноэлементное ограничение (чтобы каждый поток имел свой собственный объект file). Так что используйте

public void parse(File file) //and add synchronised if you want.
3 голосов
/ 16 марта 2010

Я думаю, что в этом коде есть несколько проблем.

  1. Если этот класс является одноэлементным, этот класс не должен содержать состояний, т.е. в этом классе не должно быть состояний. поэтому иметь установщик для самого файла не правильно. Передайте объект file в метод parse и дайте ему работать с аргументом. Это должно решить вашу проблему синхронизации между различными методами

  2. Хотя ваш набор myObjects является частным, я предполагаю, что вы не передаете его другим вызывающим классам. В этом случае всегда возвращайте клон этого набора, чтобы вызывающие абоненты не вносили изменения в исходный набор.

  3. Синхронизация на объекте достаточно хороша, если все ваши установленные изменения находятся в синхронизированном блоке.

2 голосов
/ 16 марта 2010

Используйте отдельный объект MyParser для каждого запроса на синтаксический анализ, и вам не придется иметь дело с параллелизмом (по крайней мере, в MyParser). Кроме того, тогда вы сможете по-настоящему обслуживать сразу нескольких пользователей, не заставляя их ждать или стирая результаты предыдущих заданий синтаксического анализа.

0 голосов
/ 16 марта 2010

Синглтон - это в основном красная сельдь. Ничего общего с вопросами параллелизма, которые вы рассматриваете. Что касается синхронизации, я думаю, что вы в порядке. Синхронизация метода также будет работать, несмотря на то, что myObjects является статическим , потому что является одиночным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...