作者gasbomb (虚空雷神兽)
看板mud
标题[心得] 从0开始 2.多执行绪
时间Thu Dec 5 13:36:17 2019
今天我们要来正式进入 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╠╝ ║
╚◣◢ ▄▂▄ ◣◢╩╩══════╩════╝
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 211.72.253.40 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/mud/M.1575524180.A.B87.html
※ 编辑: gasbomb (211.72.253.40 台湾), 12/05/2019 13:56:30
1F:→ typers : 建议改用 java.nio 处理 io 27.242.133.47 12/06 16:08
2F:→ typers : 多执行绪在系统做大,会有很多杂事 27.242.133.47 12/06 16:09
3F:→ typers : 需要处理 27.242.133.47 12/06 16:09