Читайте также:
|
|
Теперь, после того как вы познакомились с синхронизацией, можете иначе взглянуть на JavaBeans. Когда бы вы не создавали Bean, вы должны предполагать, что он будет использован в среде с множеством процессов. Это значит, что:
Первый пункт совершенно прост для рассмотрения, но следующий требует некоторого обдумывания. Рассмотрим пример BangBean.java, приведенный в последней главе. Тогда мы ушли от ответа на вопрос о множестве процессов игнорированием ключевого слова synchronized (который не был еще объяснен) и сделав события одноадресные (unicast). А вот тот же пример, измененный для работы в среде с множеством процессов и использованием многоадресных событий:
//: c14:BangBean2.java// You should write your Beans this way so they // can run in a multithreaded environment.import javax.swing.*;import java.awt.*;import java.awt.event.*;import java.util.*;import java.io.*;import com.bruceeckel.swing.*; public class BangBean2 extends JPanel implements Serializable { private int xm, ym; private int cSize = 20; // Circle size private String text = "Bang!"; private int fontSize = 48; private Color tColor = Color.red; private ArrayList actionListeners = new ArrayList(); public BangBean2() { addMouseListener(new ML()); addMouseMotionListener(new MM()); } public synchronized int getCircleSize() { return cSize; } public synchronized void setCircleSize(int newSize) { cSize = newSize; } public synchronized String getBangText() { return text; } public synchronized void setBangText(String newText) { text = newText; } public synchronized int getFontSize() { return fontSize; } public synchronized void setFontSize(int newSize) { fontSize = newSize; } public synchronized Color getTextColor() { return tColor; } public synchronized void setTextColor(Color newColor) { tColor = newColor; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.black); g.drawOval(xm - cSize/2, ym - cSize/2, cSize, cSize); } // This is a multicast listener, which is // more typically used than the unicast // approach taken in BangBean.java: public synchronized void addActionListener(ActionListener l) { actionListeners.add(l); } public synchronized void removeActionListener(ActionListener l) { actionListeners.remove(l); } // Notice this isn't synchronized: public void notifyListeners() { ActionEvent a = new ActionEvent(BangBean2.this, ActionEvent.ACTION_PERFORMED, null); ArrayList lv = null; // Make a shallow copy of the List in case // someone adds a listener while we're // calling listeners: synchronized(this) { lv = (ArrayList)actionListeners.clone(); } // Call all the listener methods: for(int i = 0; i < lv.size(); i++) ((ActionListener)lv.get(i)).actionPerformed(a); } class ML extends MouseAdapter { public void mousePressed(MouseEvent e) { Graphics g = getGraphics(); g.setColor(tColor); g.setFont(new Font("TimesRoman", Font.BOLD, fontSize)); int width = g.getFontMetrics().stringWidth(text); g.drawString(text, (getSize().width - width) /2, getSize().height/2); g.dispose(); notifyListeners(); } } class MM extends MouseMotionAdapter { public void mouseMoved(MouseEvent e) { xm = e.getX(); ym = e.getY(); repaint(); } } public static void main(String[] args) { BangBean2 bb = new BangBean2(); bb.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("ActionEvent" + e); } }); bb.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("BangBean2 action"); } }); bb.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("More action"); } }); Console.run(bb, 300, 300); }} ///:~Добавление synchronized для методов есть простейшее изменение. Однако помня, что addActionListener() и removeActionListener(), которые относятся к ActionListener теперь добавлены в и удалены из ArrayList, так, что можно создать необходимое количество.
Можно видеть, что метод notifyListeners() не synchronized. Он может быть вызван из более чем одного процесса за раз. Также возможно для addActionListener() или removeActionListener() быть вызванными из самого вызова notifyListeners(), что является проблемой поскольку он пересекается (traverse) в ArrayList actionListeners. Чтобы избежать этой проблемы ArrayList клонирован вне секции synchronized и клон пересечен (traversed) (в Приложении A объясняются детали клонирования). Таким образом оригинальный ArrayList может быть использован без воздействия на notifyListeners().
Метод paintComponent() также не synchronized. Решение, стоит ли синхронизировать переопределенный (overridden) метод не такое же простое как в случае когда добавляется собственный метод. В данном примере кажется, что paint() выполняется успешно, независимо от того синхронизирован он или нет. Но дополнительно необходимо рассмотреть:
Тестовая программа TestBangBean2 была изменена по сравнению с версией из предыдущей главы так, чтобы показать способность множественного приведение типов в BangBean2 через добавление дополнительных слушателей.
Дата добавления: 2015-09-11; просмотров: 64 | Поможем написать вашу работу | Нарушение авторских прав |