当前位置:七道奇文章资讯编程技术Java编程
日期:2011-03-22 16:16:00  来源:本站整理

回想Java Beans[Java编程]

赞助商链接



  本文“回想Java Beans[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
我们目前已理解了同步,接着可换从另一个角度来观察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);
  }
} ///:~
很简单便可认为办法增添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的多造型本领.
  以上是“回想Java Beans[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • 回想Java Beans
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .