按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
506
…………………………………………………………Page 508……………………………………………………………
(1) 只要可行,Bean 的所有公共方法都应同步。当然,这也带来了“同步”在运行期间的开销。若特别在意
这个问题,在关键区域中不会造成问题的方法就可保留为“不同步”,但注意这通常都不是十分容易判断。
有资格的方法倾向于规模很小(如下例的 getCircleSize())以及/或者“微小”。也就是说,这个方法调
用在如此少的代码片里执行,以至于在执行期间对象不能改变。如果将这种方法设为“不同步”,可能对程
序的执行速度不会有明显的影响。可能也将一个Bean 的所有public 方法都设为 synchronized,并只有在保
证特别必要、而且会造成一个差异的情况下,才将 synchronized关键字删去。
(2) 如果将一个多造型事件送给一系列对那个事件感兴趣的“听众”,必须假在列表中移动的时候可以添加
或者删除。
第一点很容易处理,但第二点需要考虑更多的东西。让我们以前一章提供的BangBean。java 为例。在那个例
子中,我们忽略了 synchronized 关键字(那时还没有引入呢),并将造型设为单造型,从而回避了多线程的
问题。在下面这个修改过的版本中,我们使其能在多线程环境中工作,并为事件采用了多造型技术:
//: BangBean2。java
// You should write your Beans this way so they
// can run in a multithreaded environment。
import java。awt。*;
import java。awt。event。*;
import java。util。*;
import java。io。*;
public class BangBean2 extends Canvas
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 Vector actionListeners = new Vector();
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) {
507
…………………………………………………………Page 509……………………………………………………………
fontSize = newSize;
}
public synchronized Color getTextColor() {
return tColor;
}
public synchronized void
setTextColor(Color newColor) {
tColor = newColor;
}
public void paint(Graphics 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。addElement(l);
}
public synchronized void removeActionListener(
ActionListener l) {
actionListeners。removeElement(l);
}
// Notice this isn't synchronized:
public void notifyListeners() {
ActionEvent a =
new ActionEvent(BangBean2。this;
ActionEvent。ACTION_PERFORMED; null);
Vector lv = null;
// Make a copy of the vector in case someone
// adds a listener while we're
// calling listeners:
synchronized(this) {
lv = (Vector)actionListeners。clone();
}
// Call all the listener methods:
for(int i = 0; i 《 lv。size(); i++) {
ActionListener al =
(ActionListener)lv。elementAt(i);
al。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 =
508
…………………………………………………………Page 510……………………………………………………………
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();
}
}
// Testing the BangBean2:
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〃);
}
});
Frame aFrame = new Frame(〃BangBean2 Test〃);
aFrame。addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System。exit(0);
}
});
aFrame。add(bb; BorderLayout。CENTER);
aFrame。setSize(300;300);
aFrame。setVisible(true);
}
} ///:~
很容易就可以为方法添加synchronized。但注意在addActionListener()和 removeActionListener()中,现
在添加了ActionListener,并从一个 Vector 中移去,所以能够根据自己愿望使用任意多个。
我们注意到,notifyListeners()方法并未设为“同步”。可从多个线程中发出对这个方法的调用。另外,在
对notifyListeners()调用的中途,也可能发出对addActionListener()和 removeActionListener() 的调
用。这显