Философия Java


Повторное обращение к JavaBeans - часть 3


Добавление synchronized для методов есть простейшее изменение. Однако помня, что addActionListener( ) иremoveActionListener( ), которые относятся к ActionListener теперь добавлены в и удалены из ArrayList, так, что можно создать необходимое количество.

Можно видеть, что метод notifyListeners( ) не synchronized. Он может быть вызван из более чем одного процесса за раз. Также возможно для addActionListener( ) или removeActionListener( ) быть вызванными из самого вызова notifyListeners( ), что является проблемой поскольку он пересекается (traverse) в ArrayList actionListeners. Чтобы избежать этой проблемы ArrayList клонирован вне секции synchronized и клон пересечен (traversed) (в Приложении A объясняются детали клонирования). Таким образом оригинальный ArrayList может быть использован без воздействия на notifyListeners( ).

Метод paintComponent( ) также не synchronized. Решение, стоит ли синхронизировать переопределенный (overridden) метод не такое же простое как в случае когда добавляется собственный метод. В данном примере кажется, что paint() выполняется успешно, независимо от того синхронизирован он или нет. Но дополнительно необходимо рассмотреть:

  1. Изменяет ли метод значения "критических" переменных внутри объекта? Чтобы определить, является ли переменные "критическими", необходимо определить будут ли значения прочитаны или установлены другими процессами в программе. (В этом случае чтение и установка значения фактически всегда происходит через synchronized методы, так что можно их просто проверить.) В случае с paint() ни каких изменений нет.

  2. Зависит ли метод от значения этих "критических" переменных? Если synchronized метод изменяет значение той переменной, которую использует ваш метод, то вам просто необходимо также объявить ваш метод как synchronized.  В связи с этим, можно видеть, что значение переменной cSize изменяется synchronized

    методами и, следовательно, paint() также должен быть synchronized. Однако в данном случае можно спросить, "А что ужасного произойдет в том случае, если cSize измениться во время paint()?" Когда видно, что ничего плохого, к тому же присутствует эффект самовосстановления (transient effect), можно решить оставить paint() не synchronized во избежании излишних накладных расходов при вызове synchronized метода.

  3. И в третьих, необходимо убедиться, является ли базовый класс для paint() synchronized или нет. Это не просто высказывание для сотрясания воздуха, а просто подсказка. В нашем случае например, поля, изменяемые

    через synchronized методы (такие как cSize), были перемешены в paint() формуле и могли изменить ситуацию. Однако обратите внимание, что synchronized не наследуется, так например, если метод является synchronized в базовом классе, то он не будет автоматически synchronized в переопределенном методе наследующего класса.

Тестовая программа TestBangBean2 была изменена по сравнению с версией из предыдущей главы так, чтобы показать способность множественного приведение типов в BangBean2 через добавление дополнительных слушателей.




Начало  Назад  Вперед