從0開始 2.多執行緒 - MUD Game
By Gary
at 2019-12-05T13:36
at 2019-12-05T13:36
Table of Contents
今天我們要來正式進入 multi-thread (多執行緒)的部分了
觀察之前的程式片段可以發現到有兩個 while 迴圈
一個負責建立連線, 另一個負責 echo
// 建立連線的迴圈
while (true) {
socket = server.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("歡迎來到 telnet echo server!");
// 負責與使用者互動的迴圈
String input;
while ((input = in.readLine()) != null) {
if ("quit".equalsIgnoreCase(input)) {
out.println("Bye! 歡迎下次再來");
socket.close();
break;
}
out.println("Echo: " + input);
}
}
所以我們把負責與使用者互動的部分程式抽離出來
建立一個新的 Player class, 讓原本的 ChatServer 專心處理連線就好
// Player.class
// ✂--------------請沿虛線剪下--------------
package core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
// java 中程式要支援多執行緒需要實作 Runnable 介面
public class Player implements Runnable {
private Socket socket;
private BufferedReader in;
private PrintStream out;
// 建構子, 讓每個 Player 負責管理自己的 Socket 物件
public Player(Socket socket) throws IOException {
this.socket = socket;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintStream(socket.getOutputStream());
}
// override Runnable.run() 在裡面實作我們需要的邏輯
// 其實就是之前第二個 while 迴圈的內容
@Override
public void run() {
write("歡迎來到 telnet echo server! (多執行續版本)");
try {
while (true) {
String input = read();
if ("quit".equalsIgnoreCase(input)) {
socket.close();
break;
}
write("Echo: " + input);
}
} catch (IOException ignored) {}
}
// 把之前的 in.readLine() 與 out.println() 包裝起來, 方便後續使用
public String read() throws IOException {
return in.readLine();
}
public void write(String message) {
out.println(message);
}
}
// ✂--------------請沿虛線剪下--------------
Player 實作完之後
原本的 ChatServer 的程式碼也變得比較乾淨了
// ChatServer.class
// ✂--------------請沿虛線剪下--------------
package service;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import core.Player;
public class ChatServer {
static final int PORT = 4000;
public static void main(String[] args) {
Socket socket;
try (ServerSocket server = new ServerSocket(PORT)) {
System.out.println("Server is listening port: " + PORT + " now");
while (true) {
socket = server.accept();
Player player = new Player(socket);
Thread thread = new Thread(player);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// ✂--------------請沿虛線剪下--------------
java 中只要新建一個 Thread 物件
並在建立時傳入剛才已經實作 Runnable 的 Player
接著再呼叫 thread.start(), Thread 就會去開一個新的執行緒去執行 player.run()
你現在可以嘗試多開幾個 client 試著連線到 localhost:4000
我們的 server 已經有能力同時服務許多使用者了
--
╔═◢ ◣═╦╦═════╦═════╗
║ ◤◤◤ ◥ ╠╣飛鳥ももこ╠═╗ ║
║ ▇ ▇ ║╚═════╝ ╚═╦═╣
║ ▌ ● ● ▌ ║╔══════╗╔═╩═╣
║◤ ◥ ︺█◤ ◥╠╣Momoko Asuka╠╝ ║
╚◣◢ ▄▂▄ ◣◢╩╩══════╩════╝
--
觀察之前的程式片段可以發現到有兩個 while 迴圈
一個負責建立連線, 另一個負責 echo
// 建立連線的迴圈
while (true) {
socket = server.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("歡迎來到 telnet echo server!");
// 負責與使用者互動的迴圈
String input;
while ((input = in.readLine()) != null) {
if ("quit".equalsIgnoreCase(input)) {
out.println("Bye! 歡迎下次再來");
socket.close();
break;
}
out.println("Echo: " + input);
}
}
所以我們把負責與使用者互動的部分程式抽離出來
建立一個新的 Player class, 讓原本的 ChatServer 專心處理連線就好
// Player.class
// ✂--------------請沿虛線剪下--------------
package core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
// java 中程式要支援多執行緒需要實作 Runnable 介面
public class Player implements Runnable {
private Socket socket;
private BufferedReader in;
private PrintStream out;
// 建構子, 讓每個 Player 負責管理自己的 Socket 物件
public Player(Socket socket) throws IOException {
this.socket = socket;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintStream(socket.getOutputStream());
}
// override Runnable.run() 在裡面實作我們需要的邏輯
// 其實就是之前第二個 while 迴圈的內容
@Override
public void run() {
write("歡迎來到 telnet echo server! (多執行續版本)");
try {
while (true) {
String input = read();
if ("quit".equalsIgnoreCase(input)) {
socket.close();
break;
}
write("Echo: " + input);
}
} catch (IOException ignored) {}
}
// 把之前的 in.readLine() 與 out.println() 包裝起來, 方便後續使用
public String read() throws IOException {
return in.readLine();
}
public void write(String message) {
out.println(message);
}
}
// ✂--------------請沿虛線剪下--------------
Player 實作完之後
原本的 ChatServer 的程式碼也變得比較乾淨了
// ChatServer.class
// ✂--------------請沿虛線剪下--------------
package service;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import core.Player;
public class ChatServer {
static final int PORT = 4000;
public static void main(String[] args) {
Socket socket;
try (ServerSocket server = new ServerSocket(PORT)) {
System.out.println("Server is listening port: " + PORT + " now");
while (true) {
socket = server.accept();
Player player = new Player(socket);
Thread thread = new Thread(player);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// ✂--------------請沿虛線剪下--------------
java 中只要新建一個 Thread 物件
並在建立時傳入剛才已經實作 Runnable 的 Player
接著再呼叫 thread.start(), Thread 就會去開一個新的執行緒去執行 player.run()
你現在可以嘗試多開幾個 client 試著連線到 localhost:4000
我們的 server 已經有能力同時服務許多使用者了
--
╔═◢ ◣═╦╦═════╦═════╗
║ ◤◤◤ ◥ ╠╣飛鳥ももこ╠═╗ ║
║ ▇ ▇ ║╚═════╝ ╚═╦═╣
║ ▌ ● ● ▌ ║╔══════╗╔═╩═╣
║◤ ◥ ︺█◤ ◥╠╣Momoko Asuka╠╝ ║
╚◣◢ ▄▂▄ ◣◢╩╩══════╩════╝
--
Tags:
線上
All Comments
By Ida
at 2019-12-07T17:11
at 2019-12-07T17:11
By Lauren
at 2019-12-09T20:47
at 2019-12-09T20:47
Related Posts
請問該如何賺寶石最划算
By Daph Bay
at 2019-12-05T13:08
at 2019-12-05T13:08
OWL 2020 隊伍不精確總移動里程數
By Dorothy
at 2019-12-04T23:16
at 2019-12-04T23:16
馬爾杜克道具店
By Dorothy
at 2019-12-04T22:18
at 2019-12-04T22:18
這次修正控球
By Hamiltion
at 2019-12-04T19:41
at 2019-12-04T19:41
19道奇貝林傑
By Puput
at 2019-12-04T14:39
at 2019-12-04T14:39