回首Java Beans
当前位置:以往代写 > JAVA 教程 >回首Java Beans
2019-06-14

回首Java Beans

回首Java Beans

我们此刻已领略了同步,接着可换从另一个角度来考查Java Beans。无论什么时候建设了一个Bean,就必需假定它要在一个多线程的情况中运行。这意味着:
(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) {
    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 = 
        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);
  }
} ///:~

#p#分页标题#e#

很容易就可觉得要领添加synchronized。但留意在addActionListener()和removeActionListener()中,此刻添加了ActionListener,并从一个Vector中移去,所以可以或许按照本身愿望利用任意多个。
我们留意到,notifyListeners()要领并未设为“同步”。可从多个线程中发出对这个要领的挪用。别的,在对notifyListeners()挪用的半途,也大概发出对addActionListener()和removeActionListener()的挪用。这显然会造成问题,因为它否认了Vector actionListeners。为缓解这个问题,我们在一个synchronized从句中“克隆”了Vector,并对克隆举办了否认。这样便可在不影响notifyListeners()的前提下,对Vector举办哄骗。
paint()要领也没有设为“同步”。与纯真地添加本身的要领对比,抉择是否对过载的要领举办同步要坚苦得多。在这个例子中,无论paint()是否“同步”,它好像都能正常地事情。但必需思量的问题包罗:
(1) 要了解在工具内部修改“要害”变量的状态吗?为判定一个变量是否“要害”,必需知道它是否会被措施中的其他线程读取或配置(就今朝的环境看,读取或配置险些必定是通过“同步”要领举办的,所以可以只对它们举办查抄)。对paint()的环境来说,不会产生任何修改。
(2) 要领要以这些“要害”变量的状态为基本吗?假如一个“同步”要领修改了一个变量,而我们的要领要用到这个变量,那么一般都愿意把本身的要领也设为“同步”。基于这一前提,各人可调查到cSize由“同步”要领举办了修改,所以paint()该当是“同步”的。但在这里,我们可以问:“如果cSize在paint()执行期间产生了变革,会产生的最糟糕的工作是什么呢?”假如发明环境不算太坏,并且仅仅是临时的结果,那么最好保持paint()的“差异步”状态,以制止同步要领挪用带来的特别开销。
(3) 要寄望的第三条线索是paint()基本类版本是否“同步”,在这里它不是同步的。这并不是一个很是严格的参数,仅仅是一条“线索”。好比在今朝的环境下,通过同步要领(好cSize)改变的一个字段已合成到paint()公式里,并且大概已改变了环境。但请留意,synchronized不能担任——也就是说,如果一个要领在基本类中是“同步”的,那么在衍生类过载版本中,它不会自动进入“同步”状态。
TestBangBean2中的测试代码已在前一章的基本长举办了修改,已在个中插手了特另外“听众”,从而演示了BangBean2的多造型本领。

    关键字:

在线提交作业