- 相關(guān)推薦
java遠(yuǎn)程方法調(diào)用技巧
聰明出于勤奮,天才在于積累,以下是小編為大家搜索整理java遠(yuǎn)程方法調(diào)用技巧,希望能給大家?guī)韼椭?更多精彩內(nèi)容請及時(shí)關(guān)注我們應(yīng)屆畢業(yè)生考試網(wǎng)!
概述
Java Remote Method Invocation ( RMI -- Java遠(yuǎn)程方法調(diào)用)允許您使用Java編寫分布式對象。本文將介紹RMI的優(yōu)點(diǎn)以及如何將其連接到現(xiàn)有的和原有的系統(tǒng)中,以及與用Java 編寫的組件的連接。
RMI為采用Java對象的分布式計(jì)算提供了簡單而直接的途徑。這些對象可以是新的Java對象,也可以是圍繞現(xiàn)有API的簡單的Java包裝程序。Java體現(xiàn)了“編寫一次就能在任何地方運(yùn)行的模式。而RMI可將Java模式進(jìn)行擴(kuò)展,使之可在任何地方運(yùn)行”。
因?yàn)镽MI是以Java為核心的,所以,它將Java的安全性和可移植性等強(qiáng)大功能帶給了分布式計(jì)算。您可將代理和梢務(wù)邏輯等屬性移動(dòng)到網(wǎng)絡(luò)中最合適的地方。如果您要擴(kuò)展Java在系統(tǒng)中的使用,RMI將使您充分利用其強(qiáng)大功能。
RMI可利用標(biāo)準(zhǔn)Java本機(jī)方法接口JNI與現(xiàn)有的和原有的系統(tǒng)相連接。RMI還可利用標(biāo)準(zhǔn)JDBC包與現(xiàn)有的關(guān)系數(shù)據(jù)庫連接。RMI/JNI和RMI/JDBC相結(jié)合,可幫助您利用RMI與目前使用非Java語言的現(xiàn)有服務(wù)器進(jìn)行通信,而且在您需要時(shí)可擴(kuò)展Java在這些服務(wù)器上的使用。RMI可幫助您在擴(kuò)展使用時(shí)充分利用Java的強(qiáng)大功能。
優(yōu)點(diǎn)
從最基本的角度看,RMI是Java的遠(yuǎn)程過程調(diào)用(RPC)機(jī)制。與傳統(tǒng)的RPC系統(tǒng)相比,RMI具有若干優(yōu)點(diǎn),因?yàn)樗荍ava面向?qū)ο蠓椒ǖ囊徊糠帧鹘y(tǒng)的RPC系統(tǒng)采用中性語言,所以是最普通的系統(tǒng)--它們不能提供所有可能的目標(biāo)平臺(tái)所具有的功能。
RMI以Java為核心,可與采用本機(jī)方法與現(xiàn)有系統(tǒng)相連接。這就是說,RMI可采用自然、直接和功能全面的方式為您提供分布式計(jì)算技術(shù),而這種技術(shù)可幫助您以不斷遞增和無縫的方式為整個(gè)系統(tǒng)添加Java功能。
RMI的主要優(yōu)點(diǎn)如下:
面向?qū)ο螅篟MI可將完整的對象作為參數(shù)和返回值進(jìn)行傳遞,而不僅僅是預(yù)定義的數(shù)據(jù)類型。也就是說,您可以將類似Java哈希表這樣的復(fù)雜類型作為一個(gè)參數(shù)進(jìn)行傳遞。而在目前的RPC系統(tǒng)中,您只能依靠客戶機(jī)將此類對象分解成基本數(shù)據(jù)類型,然后傳遞這些數(shù)據(jù)類型,最后在服務(wù)器端重新創(chuàng)建哈希表。RMI則不需額外的客戶程序代碼(將對象分解成基本數(shù)據(jù)類型),直接跨網(wǎng)傳遞對象。
可移動(dòng)屬性:RMI可將屬性(類實(shí)現(xiàn)程序)從客戶機(jī)移動(dòng)到服務(wù)器,或者從服務(wù)器移到客戶機(jī)。例如,您可以定義一個(gè)檢查雇員開支報(bào)告的接口,以便察看雇員是否遵守了公司目前實(shí)行的政策。在開支報(bào)告創(chuàng)建后,客戶機(jī)就會(huì)從服務(wù)器端獲得實(shí)現(xiàn)該接口的對象。如果政策發(fā)生變化,服務(wù)器端就會(huì)開始返回使用了新政策的該接口的另一個(gè)實(shí)現(xiàn)程序。您不必在用戶系統(tǒng)上安裝任何新的軟件就能在客戶端檢查限制條件--從而向用戶提供爍快的反饋,并降低服務(wù)器的工作量。這樣就能具備最大的靈活性,因?yàn)檎吒淖儠r(shí)只需要您編寫一個(gè)新的Java類,并將其在服務(wù)器主機(jī)上安裝一次即可。
設(shè)計(jì)方式:對象傳遞功能使您可以在分布式計(jì)算中充分利用面向?qū)ο蠹夹g(shù)的強(qiáng)大功能,如二層和三層結(jié)構(gòu)系統(tǒng)。如果您能夠傳遞屬性,那么您就可以在您的解決方案中使用面向?qū)ο蟮脑O(shè)計(jì)方式。所有面向?qū)ο蟮脑O(shè)計(jì)方式無不依靠不同的屬性來發(fā)揮功能,如果不能傳遞完整的對象--包括實(shí)現(xiàn)和類型--就會(huì)失去設(shè)計(jì)方式上所提供的優(yōu)點(diǎn)。
安全:RMI使用Java內(nèi)置的安全機(jī)制保證下載執(zhí)行程序時(shí)用戶系統(tǒng)的安全。RMI使用專門為保護(hù)系統(tǒng)免遭惡意小應(yīng)用程序侵害而設(shè)計(jì)的安全管理程序,可保護(hù)您的系統(tǒng)和網(wǎng)絡(luò)免遭潛在的惡意下載程序的破壞。在情況嚴(yán)重時(shí),服務(wù)器可拒絕下載任何執(zhí)行程序。
便于編寫和使用:RMI使得Java遠(yuǎn)程服務(wù)程序和訪問這些服務(wù)程序的Java客戶程序的編寫工作變得輕松、簡單。遠(yuǎn)程接口實(shí)際上就是Java接口。服務(wù)程序大約用三行指令宣布本身是服務(wù)程序,其它方面則與任何其它Java對象類似。這種簡單方法便于快速編寫完整的分布式對象系統(tǒng)的服務(wù)程序,并快速地制做軟件的原型和早期版本,以便于進(jìn)行測試和評(píng)估。因?yàn)镽MI程序編寫簡單,所以維護(hù)也簡單。
可連接現(xiàn)有/原有的系統(tǒng):RMI可通過Java的本機(jī)方法接口JNI與現(xiàn)有系統(tǒng)進(jìn)行進(jìn)行交互。利用RMI和JNI,您就能用Java語言編寫客戶端程序,還能使用現(xiàn)有的服務(wù)器端程序。在使用RMI/JNI與現(xiàn)有服務(wù)器連接時(shí),您可以有選擇地用Java重新編寫服務(wù)程序的任何部分,并使新的程序充分發(fā)揮Java的功能。類似地,RMI可利用JDBC、在不修改使用數(shù)據(jù)庫的現(xiàn)有非Java源代碼的前提下與現(xiàn)有關(guān)系數(shù)據(jù)庫進(jìn)行交互。
編寫一次,到處運(yùn)行:RMI是Java“編寫一次,到處運(yùn)行 ”方法的一部分。任何基于RMI的系統(tǒng)均可100%地移植到任何Java虛擬機(jī)上,RMI/JDBC系統(tǒng)也不例外。如果使用RMI/JNI與現(xiàn)有系統(tǒng)進(jìn)行交互工作,則采用JNI編寫的代碼可與任何Java虛擬機(jī)進(jìn)行編譯、運(yùn)行。
分布式垃圾收集:RMI采用其分布式垃圾收集功能收集不再被網(wǎng)絡(luò)中任何客戶程序所引用的遠(yuǎn)程服務(wù)對象。與Java 虛擬機(jī)內(nèi)部的垃圾收集類似,分布式垃圾收集功能允許用戶根據(jù)自己的需要定義服務(wù)器對象,并且明確這些對象在不再被客戶機(jī)引用時(shí)會(huì)被刪除。
并行計(jì)算:RMI采用多線程處理方法,可使您的服務(wù)器利用這些Java線程更好地并行處理客戶端的請求。Java分布式計(jì)算解決方案:RMI從JDK 1.1開始就是Java平臺(tái)的核心部分,因此,它存在于任何一臺(tái)1.1 Java虛擬機(jī)中。所有RMI系統(tǒng)均采用相同的公開協(xié)議,所以,所有Java 系統(tǒng)均可直接相互對話,而不必事先對協(xié)議進(jìn)行轉(zhuǎn)換。
傳遞屬性
前面我們講到,RMI可以傳遞屬性,并簡單介紹了一下一個(gè)有關(guān)開支報(bào)告程序的情況。下面我們將深入討論如何設(shè)計(jì)這樣的系統(tǒng)。這樣介紹的目的是使您能夠利用RMI的功能將屬性從一個(gè)系統(tǒng)傳遞到另一個(gè)系統(tǒng),并隨心所欲地安排當(dāng)前的計(jì)算地點(diǎn),并便于將來的改變。下面的例子并未涉及真實(shí)世界可能發(fā)生的所有問題,但可幫助讀者了解處理問題的方法。
服務(wù)器定義的策略
圖1是可進(jìn)行動(dòng)態(tài)配置的開支報(bào)告系統(tǒng)的示意圖。客戶機(jī)向用戶顯示圖形用戶界面(GUI),用戶填寫開支報(bào)告。客戶機(jī)程序使用RMI與服務(wù)器進(jìn)行通信。服務(wù)器使用JDBC( Java關(guān)系數(shù)據(jù)庫連接包)將開支報(bào)告存儲(chǔ)在數(shù)據(jù)庫中。至此,這看起來與其它多層次系統(tǒng)大同小異,但有一個(gè)重大區(qū)別-- RMI能下載屬性。
假定公司關(guān)于開支報(bào)告的政策發(fā)生改變。例如,目前公司只要求對超過20美元的開支需開具發(fā)票。但到明天,公司認(rèn)為這太寬松了,便決定除不超過20美元的餐費(fèi)以外,任何開支均需開具發(fā)票。如果不能下載屬性的話,那么在設(shè)計(jì)便于修改的系統(tǒng)時(shí)您可選擇下列方法之一:
用客戶端安裝與政策有關(guān)的程序。政策改變時(shí),必須更新包含此政策的所有客戶端程序。您可在若干服務(wù)器上安裝客戶程序,并要求所有用戶從這些服務(wù)器之一運(yùn)行客戶程序,從而減少問題。但這仍不能徹底解決問題-- 那些讓程序運(yùn)行好幾天的用戶就無法使程序更新,而總是會(huì)有一些用戶為了方便而把軟件復(fù)制到本地磁盤上。
您可要求服務(wù)器在每次向開支報(bào)告添加項(xiàng)目時(shí)檢查政策。但這樣就會(huì)在客戶機(jī)和服務(wù)器之間產(chǎn)生大量數(shù)據(jù)流,并增加服務(wù)器的工作量。這還會(huì)使系統(tǒng)變得更加脆弱--網(wǎng)絡(luò)故障會(huì)立即妨礙用戶,而不僅僅是只在其呈交開支報(bào)告或啟動(dòng)新的報(bào)告時(shí)對其產(chǎn)生影響。同時(shí),添加項(xiàng)目的速度也會(huì)變慢,因?yàn)檫@需要穿越整個(gè)網(wǎng)絡(luò)往返一圈才能到達(dá)(不堪重負(fù)的)服務(wù)器。
您可在呈交報(bào)告時(shí)要求服務(wù)器對政策進(jìn)行檢查。這樣就會(huì)使用戶創(chuàng)建很多必須待批報(bào)告的錯(cuò)誤項(xiàng)目,而不是立刻捕捉到第一個(gè)錯(cuò)誤,從而使用戶有機(jī)會(huì)停止制造錯(cuò)誤。為避免浪費(fèi)時(shí)間,用戶需要立刻得到有關(guān)錯(cuò)誤的反饋。
有了RMI,您就能以簡單的方法調(diào)用程序從服務(wù)器得到屬性,從而提供了一種靈活的方式,將計(jì)算任務(wù)從服務(wù)器卸載到客戶機(jī)上,同時(shí)為用戶提供速度更快的反饋。當(dāng)用戶準(zhǔn)備編寫一份新的開支報(bào)告時(shí),客戶機(jī)就會(huì)向服務(wù)器要求一個(gè)對象,該對象嵌入了適用于該開支報(bào)告的當(dāng)前政策,就如同通過用Java編寫的政策接口所表示的那樣。該對象可以以任何方式實(shí)現(xiàn)當(dāng)前政策。如果這是客戶機(jī)RMI首次看到這種專門執(zhí)行的政策,就會(huì)要求服務(wù)器提供一份執(zhí)行過程的副本。如果執(zhí)行過程將來發(fā)生變化,則一種新的政策對象將被返回給客戶機(jī),而RMI運(yùn)行時(shí)則會(huì)要求得到新的執(zhí)行過程。
這表明,政策永遠(yuǎn)是動(dòng)態(tài)的。您要想修改政策,就只需簡單地編寫通用政策接口的新的執(zhí)行程序,把它安裝在服務(wù)器上,并對服務(wù)器進(jìn)行配置以返回這種新類型的對象即可。這樣,每臺(tái)客戶機(jī)都會(huì)根據(jù)新的政策對新的開支報(bào)告進(jìn)行檢查。
這是一種比任何靜態(tài)方法都更好的方法,原因如下:
所有客戶機(jī)不必暫停或用新的軟件來升級(jí)--軟件可根據(jù)需要在不工作時(shí)加以更新。
服務(wù)器不必參與項(xiàng)目檢查工作,該工作可在本地完成。
允許動(dòng)態(tài)限制,因?yàn)閷ο髨?zhí)行程序(而不僅僅是數(shù)據(jù))是在客戶機(jī)和服務(wù)器之間進(jìn)行傳遞的。
使用戶能立刻看到錯(cuò)誤。
使客戶機(jī)在服務(wù)器上所能調(diào)用的方法的遠(yuǎn)程接口定義如下:
import java.rmi.*;
public interface ExpenseServer extends Remote {
Policy getPolicy() throws RemoteException;
void submitReport(ExpenseReport report)
throws RemoteException, InvalidReportException;
}
import語句輸入Java RMI包。所有RMI類型均在包java.rmi或其子包內(nèi)定義。接口ExpenseServer是一般的Java接口,具有如下兩種有趣的特點(diǎn):
它擴(kuò)展了名為Remote的RMI接口,這使該接口標(biāo)記為可用于遠(yuǎn)程調(diào)用。
它的所有方法均拋出RemoteException,后者用來表示網(wǎng)絡(luò)或信息故障。
遠(yuǎn)程方法還可拋出您所需要的任何其他例外,但至少必須拋出RemoteException,這樣您才能處理只會(huì)在分布式系統(tǒng)中發(fā)生的錯(cuò)誤狀態(tài)。該接口本身支持兩個(gè)方法:getPolicy (返回一個(gè)實(shí)現(xiàn)政策接口的對象),和submitReport (提交一個(gè)完成的開支請求,并在報(bào)告無論因何種原因使表格出現(xiàn)錯(cuò)誤時(shí),拋出一個(gè)例外)。
政策接口本身可聲明一種使客戶機(jī)知道能否在開支報(bào)告中添加一個(gè)項(xiàng)目的方法:
public interface Policy {
void checkValid (Expenseentry entry)
throws PolicyViolationException;
}
如果該項(xiàng)目有效--即符合當(dāng)前政策,則該方法可正常返回。否則就會(huì)拋出一個(gè)描述該錯(cuò)誤的例外。政策接口是本地的(而非遠(yuǎn)程的),所以將通過本機(jī)對象在客戶機(jī)上執(zhí)行--在客戶機(jī)的虛擬機(jī)上,而非整個(gè)網(wǎng)絡(luò)上運(yùn)行的對象。客戶機(jī)可能運(yùn)行下列程序:
Policy curPolicy = server.getPolicy();
start a new expense report
show the GUI to the user
while (user keeps adding entries) {
try {
curPolicy.checkValid(entry); // throws exception if not OK
add the entry to the expense report
} catch (PolicyViolationException e) {
show the error to the user
}
}
server.submitReport(report);
當(dāng)用戶請求客戶機(jī)軟件啟動(dòng)一份新的開支報(bào)告時(shí),客戶機(jī)就調(diào)用server.getPolicy,并要求服務(wù)器返回一個(gè)包含當(dāng)前開支政策的對象。添加的每個(gè)項(xiàng)目首先都被提交給該政策對象,以獲得批準(zhǔn)。如果政策對象報(bào)告無錯(cuò)誤,則該項(xiàng)目就被添加到報(bào)告中;否則錯(cuò)誤就被顯示給用戶,而后者可采取修正措施。當(dāng)用戶完成向報(bào)告中添加項(xiàng)目時(shí),整個(gè)報(bào)告就被呈交。服務(wù)程序如下:
import java.rmi. *;
import java.rmi.server. *;
class ExpenseServerImpl
extends UnicastRemoteObject
implements ExpenseServer
{
ExpenseServerImpl() throws RemoteException {
// . . . set up server state . . .
}
public Policy getPolicy() {
return new TodaysPolicy();
}
public void submitReport(ExpenseReport report) {
// . . . write the report into the db . . .
}
}
除基本程序包外,我們還輸入RMI的服務(wù)程序包。類型UnicastRemoteObject 定義了此服務(wù)程序遠(yuǎn)程對象的類型,在本例中,應(yīng)為單一服務(wù)程序而非復(fù)制服務(wù)(下面還會(huì)詳細(xì)介紹)。Java類ExpenseSeverImpl實(shí)現(xiàn)遠(yuǎn)程接ExpenseServer的方法。遠(yuǎn)程主機(jī)的客戶機(jī)可使用RMI將信息發(fā)送給ExpenseServerImpl對象。
本文中討論的重要方法是getPolicy,它簡單地返回定義當(dāng)前政策的對象。下面看一個(gè)執(zhí)行政策的例子:
public class TodaysPolicy implements Policy {
public void checkValid(ExpenseEntry entry)
throws PolicyViolationException
{
if (entry.dollars() < 20) {
return; // no receipt required
else if (entry.haveReceipt() == false) {
throw new PolicyViolationException;
}
}
}
TodaysPolicy進(jìn)行檢查的目的是確保無收據(jù)的任何項(xiàng)目均少于20美元。如果將來政策發(fā)生變化,僅少于20美元的餐費(fèi)可不受“需要收據(jù)”政策的限制,則您可提供新的政策實(shí)現(xiàn):
public class TomorrowsPolicy implements Policy {
public void checkValid(ExpenseEntry entry)
throws PolicyViolationException
{
if (entry.isMeal() && entry.dollars() < 20) {
return; // no receipt required
} else if (entry.haveReceipt() == false) {
throw new PolicyViolationException;
}
}
}
編寫這個(gè)類,并把它安裝在服務(wù)器上,然后告訴服務(wù)器開始提供TomorrowsPolicy對象,而非daysPolicy對象,這樣您的整個(gè)系統(tǒng)就會(huì)開始使用新的政策。當(dāng)客戶機(jī)調(diào)用服務(wù)器的getPolicy方法時(shí),客戶機(jī)的RMI就會(huì)檢查返回的對象是否為已知類型。每臺(tái)客戶機(jī)首次遇到TomorrowsPolicy時(shí),RMI就會(huì)在getPolicy返回前下載政策的實(shí)現(xiàn)。客戶機(jī)可輕松地開始增強(qiáng)這個(gè)新的政策。
RMI使用標(biāo)準(zhǔn)Java對象序列化機(jī)制傳遞對象。引用遠(yuǎn)程對象參數(shù)作為遠(yuǎn)程引用傳遞。如果向某方法提供的參數(shù)為原始類型或本機(jī)(非遠(yuǎn)程)對象,則向服務(wù)器傳遞一個(gè)深副本。返回值也拾照同樣的方式處理,只不過是沿其它方向。RMI可使用戶向本機(jī)對象傳遞和返回完整對象圖并為遠(yuǎn)程對象傳遞和返回引用。
在真實(shí)的系統(tǒng)中,getPolicy方法可能會(huì)有一個(gè)可以識(shí)別用戶及開支報(bào)告類型(差旅、客戶關(guān)系等)的參數(shù),這樣可使政策加以區(qū)別。您或者可以不要求單獨(dú)的政策和開支報(bào)告對象,但您可以有一種newExpenseReport方法,它可返回一個(gè)直接檢查政策的ExpenseReport對象。這最后一種策略可使您像修改政策一樣簡單地修改開支報(bào)告的內(nèi)容--當(dāng)公司決定需要把餐費(fèi)劃分為早餐、午餐和晚餐項(xiàng)目,而且像上述修改政策一樣簡單地執(zhí)行修改時(shí)--可編寫一個(gè)實(shí)現(xiàn)該報(bào)告的新類,客戶程序就會(huì)自動(dòng)使用這個(gè)類。
計(jì)算服務(wù)器
開支報(bào)告的例子表示了客戶機(jī)如何從服務(wù)器得到屬性。屬性可沿兩個(gè)方向傳遞--客戶機(jī)也可將新的類型傳遞給用戶。最簡單的例子就是如圖2所示的計(jì)算服務(wù)器,該服務(wù)程序可執(zhí)行任意任務(wù),這樣整個(gè)企業(yè)內(nèi)的客戶機(jī)都能利用高端或?qū)S糜?jì)算機(jī)。
任務(wù)由一個(gè)簡單的本地(非遠(yuǎn)程)接口定義:
public interface Task {
Object run();
}
運(yùn)行時(shí),它就會(huì)進(jìn)行一些計(jì)算,并返回一個(gè)包含結(jié)果的對象。這完全是一般性的任務(wù)--幾乎所有計(jì)算任務(wù)都可在這個(gè)接口下實(shí)現(xiàn)。遠(yuǎn)程接口ComputeServer也同樣簡單:
import java.rmi.*;
public interface ComputeServer extends Remote {
Object compute(Task task) throws RemoteException;
}
這個(gè)遠(yuǎn)程接口的唯一目的就是使客戶機(jī)創(chuàng)建一個(gè)Task (任務(wù))對象,并把它發(fā)送給服務(wù)器執(zhí)行,最后返回結(jié)果。該服務(wù)器的基本實(shí)現(xiàn)如下:
import java.rmi.*;
import java.rmi.server.*;
public class ComputeServerImpl
extends UnicastRemoteObject
implements ComputeServer
{
public ComputeServerImpl() throws RemoteException { }
public Object compute(Task task) {
return task.run();
}
public static void main(String[] args) throws Exception {
// use the default, restrictive security manager
System.setSecurityManager(new RMISecurityManager());
ComputeServerImpl server = new ComputeServerImpl();
Naming.rebind("ComputeServer", server);
System.out.println("Ready to receive tasks");
return;
}
}
如果您看一看compute方法就會(huì)發(fā)現(xiàn),它非常簡單。它只是接受傳遞給它的對象,并返回計(jì)算的結(jié)果。main方法包括服務(wù)器的啟動(dòng)代碼--它安裝了RMI的缺省安全管理程序,以防止他人存取本地系統(tǒng),并創(chuàng)建可處理進(jìn)入的請求的ComputeServerImpl對象,并將其與名字"ComputeServer"關(guān)聯(lián)。這時(shí),服務(wù)器已經(jīng)準(zhǔn)備好接收要執(zhí)行的任務(wù),而main 也完成了其設(shè)置。
如上所述,這實(shí)際上是一種全面和實(shí)用的服務(wù)。系統(tǒng)可以得到改進(jìn),比如,可添加要計(jì)算的參數(shù),從而對使用服務(wù)程序的部門進(jìn)行計(jì)費(fèi)。但在很多情況下,上述接口和及其實(shí)現(xiàn)允許使用高端計(jì)算機(jī)進(jìn)行遠(yuǎn)程計(jì)算。這又明了RMI的簡單性--如果您鍵入上述類,對其進(jìn)行編譯,并啟動(dòng)服務(wù)程序,您就擁有了能執(zhí)行任意任務(wù)的運(yùn)行計(jì)算服務(wù)器。
下面介紹一個(gè)使用這種計(jì)算服務(wù)的例子。假定您購買了一個(gè)能運(yùn)行大量計(jì)算操作應(yīng)用程序的非常高端的系統(tǒng)。管理員可在該系統(tǒng)上啟動(dòng)一個(gè)Java虛擬機(jī),運(yùn)行ComputeServerImpl對象。該對象現(xiàn)在就可接受要運(yùn)行的任務(wù)。
現(xiàn)在假定一個(gè)小組準(zhǔn)備通過一組數(shù)據(jù)培訓(xùn)一個(gè)神經(jīng)網(wǎng)絡(luò),以幫助制訂采購策略。他們可以采用的步驟如下:
定義一個(gè)類--暫且稱之為PurchaseNet。它能接受一組數(shù)據(jù),并運(yùn)行培訓(xùn)數(shù)據(jù),返回一個(gè)經(jīng)過培訓(xùn)的神經(jīng)網(wǎng)絡(luò)。PurchaseNet 將實(shí)現(xiàn)Task (任務(wù))接口,并在其run方法中執(zhí)行其工作。他們可能還需要一個(gè)Neuron類來描述所返回的網(wǎng)絡(luò)中的節(jié)點(diǎn),而且很可能需要其它類來描述處理過程。run方法將返回一個(gè)由一組經(jīng)過培訓(xùn)的Neuron對象組成的NeuralNet對象。
當(dāng)這些類被編寫好并進(jìn)行小規(guī)模測試時(shí),用一個(gè)PurchaseNet 對象調(diào)用ComputeServer的compute方法。
當(dāng)ComputeServerImpl對象中的RMI系統(tǒng)接收到作為進(jìn)入?yún)?shù)的 PurchaseNet對象時(shí),它就下載PurchaseNet的實(shí)現(xiàn),并調(diào)用該服務(wù)器的compute方法,并把該對象作為Task (任務(wù))參數(shù)。
Task,也就是PurchaseNet對象,將開始執(zhí)行其執(zhí)行程序。當(dāng)執(zhí)行程序需要諸如Neuron和NeuralNet等新的類時(shí),它們可根據(jù)需要下載。
所有計(jì)算都將在計(jì)算服務(wù)器上執(zhí)行,而客戶機(jī)線程則等待結(jié)果。(客戶機(jī)系統(tǒng)上的另一個(gè)線程則會(huì)顯示“正在等待”光標(biāo)或使用Java的內(nèi)置并行機(jī)制執(zhí)行另一個(gè)任務(wù) )。當(dāng)運(yùn)行返回其NeuralNet對象時(shí),這個(gè)對象將作為compute 方法的結(jié)果被傳遞回客戶機(jī)。
這不需要在服務(wù)器上安裝其它軟件--所有必須完成的任務(wù)都由各部門在其自己的計(jì)算機(jī)上完成,隨后再根據(jù)需要傳遞給計(jì)算服務(wù)器主機(jī)。
這個(gè)簡單的計(jì)算服務(wù)器體系結(jié)構(gòu)為系統(tǒng)的分布式功能提供了功能強(qiáng)大的轉(zhuǎn)換能力。一項(xiàng)任務(wù)的計(jì)算可以被轉(zhuǎn)移到一個(gè)能為其提供最好支持的系統(tǒng)上完成。這樣的系統(tǒng)可以被用來:
在ComputeServerImpl對象運(yùn)行于有數(shù)據(jù)挖掘需要的主機(jī)上,支持?jǐn)?shù)據(jù)挖掘應(yīng)用程序。這樣可使您輕松地把任何計(jì)算移動(dòng)到數(shù)據(jù)所在的地方。
在從當(dāng)前股票價(jià)格、發(fā)貨信息或其它實(shí)時(shí)信息等外部資源獲得直接數(shù)據(jù)的服務(wù)器上運(yùn)行計(jì)算任務(wù)。
通過運(yùn)行ComputeServer (接受進(jìn)入的請求并將其轉(zhuǎn)送到運(yùn)行 ComputeServerImpl的負(fù)擔(dān)最小的服務(wù)器上)的不同實(shí)現(xiàn),而將任務(wù)分布在多個(gè)服務(wù)器上。
代理
因?yàn)镽MI允許使用Java實(shí)現(xiàn)下載屬性,所以您可使用RMI 編寫代理系統(tǒng)。代理的最簡單格式如下:
import java.rmi.*;
public interface AgentServer extends Remote {
void accept(Agent agent)
throws RemoteException, InvalidAgentException;
}
public interface Agent extends java.io.Serializable {
void run();
}
啟動(dòng)一個(gè)代理也就創(chuàng)建了實(shí)現(xiàn)Agent (代理)接口、找到服務(wù)器、激活接受該代理對象的類。該代理的執(zhí)行程序?qū)⒈幌螺d到服務(wù)器上運(yùn)行。accept方法將啟動(dòng)一個(gè)該代理的新線程,激活其run方法,然后返回,從而使該代理一直執(zhí)行到run方法返回為止。代理可通過激活在另一臺(tái)主機(jī)上運(yùn)行的服務(wù)程序的accept方法而移植到該主機(jī),而其本身則作為將被接受的代理來傳遞,并結(jié)束其在原來主機(jī)上的線程。
面向?qū)ο蟮拇a重用與設(shè)計(jì)模式
面向?qū)ο蟮木幊淌且豁?xiàng)允許代碼重用的強(qiáng)大技術(shù)。很多企業(yè)組織都使用面向?qū)ο蟮木幊虂頊p輕創(chuàng)建程序的負(fù)擔(dān)和提高系統(tǒng)的靈活性。RMI是完全面向?qū)ο蟮?-信息被發(fā)送給遠(yuǎn)程對象,而且對象可以被傳遞和返回。
Design Patterns (設(shè)計(jì)模式)目前在描述面向?qū)ο笤O(shè)計(jì)的實(shí)踐活動(dòng)中獲得了相當(dāng)大的成功。首先是因?yàn)镈esign Patterns 的創(chuàng)新工作而使之大受歡迎,這些編程方式是一種正式描述解決某類特定問題的完整方法的途徑。所有這些設(shè)計(jì)模式都依賴于創(chuàng)建一個(gè)或多個(gè)抽象概念,這些抽象概念允許不同的實(shí)現(xiàn),從而允許和增強(qiáng)軟件重用。軟件重用是面向?qū)ο蠹夹g(shù)的主要優(yōu)勢,而設(shè)計(jì)模式則是促進(jìn)重用的最受歡迎的技術(shù)之一。
所有設(shè)計(jì)模式都依賴面向?qū)ο蟮亩鄳B(tài)性--這是對象( 如Task )擁有多個(gè)實(shí)現(xiàn)的能力。算法的普通部分(如compute 方法)不必知道使用了哪個(gè)實(shí)現(xiàn),它只需知道得到一個(gè)對象后應(yīng)該對該對象采取什么操作。特別地,計(jì)算服務(wù)器就是Command (指令)模式的一個(gè)例子,它可使您將請求 (任務(wù))表示為對象,并對其進(jìn)行調(diào)度。
只有當(dāng)包括執(zhí)行程序在內(nèi)的完整對象能在客戶機(jī)和服務(wù)器之間傳遞時(shí),才會(huì)存在這樣的多態(tài)性。DCE和DCOM等傳統(tǒng)的RPC系統(tǒng)以及CORBA等基于對象的RPC系統(tǒng)不能下載并執(zhí)行程序,因?yàn)樗鼈儾荒馨颜鎸?shí)對象作為參數(shù)傳遞,而只能傳遞數(shù)據(jù)。
RMI可傳遞包括執(zhí)行程序在內(nèi)的所有類型,所以您可以在分布式計(jì)算解決方案中,而不僅僅是本地計(jì)算中使用面向?qū)ο蟮木幊?-包括設(shè)計(jì)方式。如果沒有RMI這樣完全面向?qū)ο蟮南到y(tǒng),那么您就必須放棄很多分布式計(jì)算系統(tǒng)中的設(shè)計(jì)方式--以及面向?qū)ο蟮能浖赜玫钠渌问健?/p>
【java遠(yuǎn)程方法調(diào)用技巧】相關(guān)文章:
Java遠(yuǎn)程方法調(diào)用RMI03-18
java構(gòu)造函數(shù)調(diào)用技巧03-27
Java程序調(diào)用C/C++語言函數(shù)的方法12-01
java調(diào)用c函數(shù)的實(shí)例04-03
Think in Java之構(gòu)造器的真正調(diào)用順12-01
Java語言的學(xué)習(xí)技巧11-27