您好,登錄后才能下訂單哦!
考慮到你要完成的任務,一個applet,甚至幾個獨立的applet,有時可能都不夠。還好,applet之間可以通訊,通過協作它們可以完成一些更復雜的任務。一組協作的applet所能產生的效能使單個applet所不能媲美的。
Applet之間的通訊可以通過傳統方法實現:applet可以互相調用對方的成員方法或者通過socket或數據流通訊。事實上,applet間互相查找的途徑有很多,每一種方法都有自身的優缺點。本文將討論四種通訊機制,并給出一個較為復雜的例子,在這個例子中我們將使用其中一種通訊機制。
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 parameters go here -->
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.
Used Applets Sale!
msnet.tjg.ColorRelay.class"
width=50 height=50 name="first">
Low, low prices!
width=50 height=50>
This week only!
width=50 height=50>
We won't be undersold!
清單 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 (Mailto:chenyuan_tongji@sian.com">chenyuan_tongji@sian.com)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。