Applet间的通讯(1)--Tricks of the Java Programming Gurus

类别:Java 点击:0 评论:0 推荐:

 

 

Tricks
     of the
      Java Programming Gurus by Glenn L. Vanderburg. et al. 1.Applet间的通讯

  目录 getApplet: 官方机制 静态变量和方法 网络通讯 基于线程的通讯 总结

    考虑到你要完成的任务,一个applet,甚至几个独立的applet,有时可能都不够。还好,applet之间可以通讯,通过协作它们可以完成一些更复杂的任务。一组协作的applet所能产生的效能使单个applet所不能媲美的。

    Applet之间的通讯可以通过传统方法实现:applet可以互相调用对方的成员方法或者通过socket或数据流通讯。事实上,applet间互相查找的途径有很多,每一种方法都有自身的优缺点。本文将讨论四种通讯机制,并给出一个较为复杂的例子,在这个例子中我们将使用其中一种通讯机制。 getApplet: “官方”机制

    Java API 本身就有用来支持applet程序间协作的特性:AppletContext 类的 getApplet 和 getApplets 方法。设有这两个函数,applet程序可以通过名称查找并访问对方。你可以这样调用 getApplet: Applet friend = getAppletContext().getApplet("Friend");

    一旦调用结束,变量 friend 就成了名为"Friend"的applet的一个实例(instance) (如果这样的一个"Friend"applet存在的话)。例如:如果 "Friend" 是 Sun的 Animator applet 的一个实例,friend 将包含对这个实例的一个参考(reference)。

    Applet的名字是在HTML中指定的,而不是在Java代码中。为了创建一个能被前面的实例代码所发现的animator applet,你可以在HTML插入如下几行: <applet code="Animator.class" width=25 height=25 name="Friend">
<!-- applet parameters go here -->
</applet>

    getApplets 方法和 getApplet 差不多,只不过getApplets返回一个Enumeration,其中列举了所有可以进行访问的applet。然后我们就可以根据applet的不同属性来查询一个applet,包括applet的名字。下面示范了如何用getApplets查找一个名为"Friend" 的applet: Applet friend;
for( Enumeration e = getAppletContext().getApplets();e.hasMoreElements(); ){
    try {
        Applet t = (Applet) e.nextElement();
        if ("Friend".equals(t.getParameter("name"))) {
            friend = t;
            break;
        }
    }
    catch (ClassCastException e) {
    }
}

    显然,上述方法的工作很多,你不会用这种途径去查找一个applet。然而,如果你要查询多个applet,或是你不知道你所要查找的applet的确切的名字,这将是一种行之有效的方法。举个例子来说,用getApplets查找所有以"Helper­"开头命名的applet将会很容易,你的applet就可以和同一页面中的所有的helper applet通讯了。

    不幸的是,这种官方推荐的applet通讯机制至少有两大问题。首先,这种机制目前并没有被具体化,因此不同的应用程序对该机制有不同的实现。例如,getApplets 返回的是可以访问的applet,但是什么是可以访问?没有明确的定义。你可能得到的是同一页面上的applet,从同一个站点加载的applet,或者是两者的交集,这些都取决于运行applet的浏览器。这些问题因该促使Sun和Java's licensees制定出一个更加严密的,明确定义的applet协作机制。不过目前为止,这种applet通讯及值的不一致实现仍然是个令人头痛的问题。

    另外一个问题就没有这么简单了。它看起来很容易理解,但它会使事情复杂到令很多applet程序员吃惊的地步。问题出在 getApplet 和 getApplets 不会让你得到一个还没有完全加载并初始化了的applet。由于网络的不确定和其他因素,例如applet的大小,我们不能决定页面上哪一个applet首先被加载,哪一个最后被加载。这就意味着我们原来的计划:首先启动并控制一个applet,查找其他applet,然后同它们协作,如果不增加额外的处理的话,是不能够达到预期目的的。

    当然了,解决上述问题有很多方法。控制applet可以检查它的协作伙伴,如果它们还没有就绪,就进入等待睡眠(一秒钟左右),然后再次协作applet的状态,直到所有协作成员都已被初始化过。虽然这种方法效率很低,会导致较长的启动时间,怎么说它还是有效的。一个更好的解决方法是“双向查找、提醒机制”(two-way search-and-notification mechanism),当一个applet初始化完成后,控制这个applet查找其他applet并通知它们“我准备好了”。使用这种机制,所有辅助applet(helpers initialize)初始化完成后,主控applet将能够立即找到它们并开始协作,如果哪个辅助appplet迟一步完成初始化,主控applet也会被及时通知。 静态变量和方法

    很多情况下,我们可以通过使用一个通用类的静态成员变量和方法构造一个内部applet通讯机制。如果多个applet都依赖于这个通用类,它们就可以把这个类作为一个消息的汇集点(rendezvous point),在那里注册它们的存在并察看其他applet的存在。

    这里有个例子。如果在一个页面上ColorRelay applet被使用多次,不同的实例通过协作显示不同的图片(一些不同颜色的打字机色带)。你可以想象这些applet依靠一个标志位。如果一个applet显示了彩色的图片,其他的只能现实黑白的图片。图 1.1 是运行时的截图,清单 1.1 是 HTML 代码。

图 1.1 : ColorRelay applet 运行中


清单 1.1. ColorRelay.html.
<html>
<body>
<h1>Used Applets Sale!</h1>

<p>
<applet align=baseline code="COM.MCP.Samsnet.tjg.ColorRelay.class"
width=50 height=50 name="first">
<param name="flashColor" value="0x0000ff">
<param name="sleepTime" value="1">
<param name="image" value="spiral.gif">
</applet>
Low, low prices!

<p>
<applet align=baseline code="COM.MCP.Samsnet.tjg.ColorRelay.class"
width=50 height=50>
<param name="flashColor" value="0x00ff00">
</applet>
This week only!

<p>
<applet align=baseline code="COM.MCP.Samsnet.tjg.ColorRelay.class"
width=50 height=50>
<param name="flashColor" value="0xff0000">
<param name="sleepTime" value="3">
</applet>
We won't be undersold!

</html>

清单 1.2 展示了 ColorRelay applet的程序框架,具体方法用注释代替了。我们将在后面的清单中提供完整的代码。 清单 1.2. ColorRelay.java (part 1).
/*
* ColorRelay.java       1.0 96/04/14 Glenn Vanderburg
*/

package COM.MCP.Samsnet.tjg;

import java.applet.*;
import java.awt.*;
import java.awt.image.*;

/**
* An applet which coordinates with other instances of itself on a Web
* page to alternately flash copies of an image in different colors.
*
* @version     1.0, 14 Mar 1996
* @author      Glenn Vanderburg
*/

public class ColorRelay extends Applet implements Runnable
{
    // These are used to maintain the list of active instances
    static ColorRelay list, listTail;
    ColorRelay next, prev;

    // This thread switches between instances
    static Thread relayer;

    // This is the original, unmodified base image which all
    // of the instances use.
    static Image originalImage;

    // The color that this instance uses to flash.  White is the default.
    Color flashColor = Color.white;

    // The modified, colorized image.
    Image modifiedImage;

    // The image currently being displayed.  This reference
    // alternates between originalImage and modifiedImage.
    Image image;

    // We use a media tracker to help manage the images.
    MediaTracker tracker;

    // The time we wait while flashing.  Two seconds is the default.
    int sleepSecs = 2;

    // Method: static synchronized
    //                addToList(ColorRelay elem)        Listing 1.3
    // Method: static synchronized
    //                removeFromList(ColorRelay elem)   Listing 1.3
    // Method: public init()                            Listing 1.4
    // Method: public start()                           Listing 1.5
    // Method: public stop()                            Listing 1.5
    // Method: public run()                             Listing 1.5
    // Method: public getAppletInfo()                   on CD
    // Method: public getParameterInfo ()               on CD
    // Method: public paint(Graphics g)                 on CD
    // Method: public update(Graphics g)                on CD
    // Method:        flash()                           on CD
    // Method:        parseRGB(String str)              on CD
}

    正如你看到的那样,程序中有一些普通的变量:两个Iamge,一个Color,一个MediaTracker,一个时间值,还有两个静态方法用来将 ColorRelay 对象插入链表。此外还有四个静态变量:originalImage, 当applet没有轮到发亮时显示;一个线程对象,用来协调applet之间的活动,还有applet链表的首位节点。

未完,待续。

翻译:chenyuan_tongji ([email protected])

本文地址:http://com.8s8s.com/it/it18556.htm