---- 摘要:在Java出現之前,編寫多線程程式是一件煩瑣且伴隨許多不安全因素的事情。利用Java,編寫安全高效的多線程程式變得簡單,而且利用多線程和Java的網路包我們可以方便的實現多線程伺服器程式。
---- Java是伴隨Internet的大潮產生的,對網路及多線程具有內在的支援,具有網路時代程式設計語言的一切特點。從Java的當前應用看,Java主要用於在Internet或區域網路上的網路編程,而且將Java作為主流的網路程式設計語言的趨勢愈來愈明顯。實際工作中,我們除了使用商品化的伺服器軟體外,時常需要按照實際環境編寫自己的伺服器軟體,以完成特定任務或與特定用戶端軟體實現互動。在實現伺服器程式時,為提高程式運行效率,降低使用者等待時間,我們應用了在Java Applet中常見的多線程技術。
---- 一、Java中的伺服器程式與多線程
---- 在Java之前,沒有一種主流程式設計語言能夠提供對進階網路編程的固有支援。在其他語言環境中,實現網路程式往往需要深入依賴於操作平台的網路API的技術中去,而Java提供了對網路支援的無平台相關性的完整軟體包,使程式員沒有必要為系統網路支援的細節而煩惱。
---- Java軟體包內在支援的網路通訊協定為TCP/IP,也是當今最流行的廣域網路/區域網路協議。Java有關網路的類及介面定義在java.net包中。用戶端軟體通常使用java.net包中的核心類Socket與伺服器的某個連接埠建立串連,而伺服器程式不同於客戶機,它需要初始化一個連接埠進行監聽,遇到串連呼叫,才與相應的客戶機建立串連。Java.net包的ServerSocket類包含了編寫伺服器系統所需的一切。下面給出ServerSocket類的部分定義。
public class ServerSocket {
public ServerSocket(int port)
throws IOException ;
public Socket accept() throws IOException ;
public InetAddress getInetAddress() ;
public int getLocalPort() ;
public void close() throws IOException ;
public synchronized void setSoTimeout
(int timeout) throws SocketException ;
public synchronized int
getSoTimeout() throws IOException ;
}
---- ServerSocket構造器是伺服器程式啟動並執行基礎,它將參數port指定的連接埠初始化作為該伺服器的連接埠,監聽客戶機串連請求。Port的範圍是0到65536,但0到1023是標準Internet協議保留連接埠,而且在Unix主機上,這些連接埠只有root使用者可以使用。一般自訂的連接埠號碼在8000到16000之間。僅初始化了ServerSocket還是遠遠不夠的,它沒有同客戶機互動的通訊端(Socket),因此需要調用該類的accept方法接受客戶呼叫。Accept()方法直到有串連請求才返回通訊通訊端(Socket)的執行個體。通過這個執行個體的輸入、輸出資料流,伺服器可以接收使用者指令,並將相應結果回應客戶機。ServerSocket類的getInetAddress和getLocalPort方法可得到該伺服器的IP地址和連接埠。setSoTimeout和getSoTimeout方法分別是設定和得到伺服器逾時設定,如果伺服器在timout設定時間內還未得到accept方法返回的通訊端執行個體,則拋出IOException的異常。
---- Java的多線程可謂是Java編程的精華之一,運用得當可以極大地改善程式的回應時間,提高程式的並行性。在伺服器程式中,由於往往要接收不同客戶機的同時請求或命令,因此可以對每個客戶機的請求產生一個命令處理線程,同時對各使用者的指令作出反應。在一些較複雜的系統中,我們還可以為每個資料庫查詢指令產生單獨的線程,並行對資料庫進行操作。實踐證明,採用多線程設計可以很好的改善系統的響應,並保證使用者指令執行的獨立性。由於Java本身是"安全執行緒"的,因此有一條編程原則是能夠獨立在一個線程中完成的操作就應該開闢一個新的線程。
---- Java中實現線程的方式有兩種,一是產生Thread類的子類,並定義該子類自己的run方法,線程的操作在方法run中實現。但我們定義的類一般是其他類的子類,而Java又不允許多重繼承,因此第二種實現線程的方法是實現Runnable介面。通過覆蓋Runnable介面中的run方法實現該線程的功能。本文例子採用第一種方法實現線程。