首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 多執行緒伺服器實作:同時服務多個客戶端

     編輯:Java 相關知識

從單一客戶到多客戶並發

JabberServer 雖能運作,但每次只能服務一個客戶端。典型伺服器需同時處理多個客戶請求,關鍵在於多執行緒機制。對不支援多執行緒的語言,這極其困難;但 Java 對多執行緒處理已盡可能簡化,讓伺服器控制多個客戶並非難事。

基本架構:每連線一執行緒

最基本做法:伺服器建立單一 ServerSocket,呼叫 accept() 等待新連線。一旦 accept() 回傳,取得 Socket,用它新建一個執行緒,專門服務該特定客戶。然後再次呼叫 accept() 等待下一個連線請求。

多執行緒伺服器程式碼

//: MultiJabberServer.java
import java.io.*;
import java.net.*;

class ServeOneJabber extends Thread {
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;

    public ServeOneJabber(Socket s) throws IOException {
        socket = s;
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
        start(); // 呼叫 run()
    }

    public void run() {
        try {
            while (true) {
                String str = in.readLine();
                if (str.equals("END")) break;
                System.out.println("Echoing: " + str);
                out.println(str);
            }
            System.out.println("closing...");
        } catch (IOException e) { }
        finally {
            try { socket.close(); } catch(IOException e) {}
        }
    }
}

public class MultiJabberServer {
    static final int PORT = 8080;
    public static void main(String[] args) throws IOException {
        ServerSocket s = new ServerSocket(PORT);
        System.out.println("Server Started");
        try {
            while(true) {
                Socket socket = s.accept(); // 阻塞直到連線
                try {
                    new ServeOneJabber(socket);
                } catch(IOException e) {
                    socket.close(); // 建構子失敗時關閉 socket
                }
            }
        } finally {
            s.close();
        }
    }
} ///:~

關鍵設計細節

  • 執行緒啟動: 建構子中呼叫 start(),完成執行緒初始化並調用 run()
  • 資源清理: Socket 在 ServeOneJabber 外部建立,清理責任「共享」。建構子失敗拋出例外由呼叫者清理;成功則由執行緒在 run() 的 finally 區塊關閉
  • 主迴圈簡潔: MultiJabberServer 僅負責 accept() 並將 Socket 傳給建構子,連線中斷後執行緒自然消失

多客戶端測試程式

為驗證伺服器能同時服務多客戶,下列程式建立多個客戶執行緒連接同一伺服器。每個執行緒「壽命」有限,到期釋放空間給新執行緒。最大執行緒數由 MAX_THREADS 控制——設太大可能耗盡資源導致不可預期錯誤。

//: MultiJabberClient.java
class JabberClientThread extends Thread {
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    private static int counter = 0;
    private int id = counter++;
    private static int threadcount = 0;
    // ... 建構子建立連線、啟動執行緒
    public void run() {
        try {
            for(int i = 0; i < 25; i++) {
                out.println("Client " + id + ": " + i);
                String str = in.readLine();
                System.out.println(str);
            }
            out.println("END");
        } catch(IOException e) { }
        finally {
            try { socket.close(); } catch(IOException e) {}
            threadcount--;
        }
    }
}

public class MultiJabberClient {
    static final int MAX_THREADS = 40;
    public static void main(String[] args) throws IOException, InterruptedException {
        InetAddress addr = InetAddress.getByName(null);
        while(true) {
            if(JabberClientThread.threadCount() < MAX_THREADS)
                new JabberClientThread(addr);
            Thread.currentThread().sleep(100);
        }
    }
} ///:~

執行緒計數與資源控制

threadcount 追蹤目前存在的 JabberClientThread 數量,建構子遞增,run() 結束時遞減。main() 中檢查執行緒數量,過多則暫不建立,進入睡眠。可嘗試逐漸增大 MAX_THREADS,觀察系統資源降至危險程度的臨界點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved