如何在重写的run()方法中使用已创建对象(TCP聊天场景)
TCP点对点聊天程序线程拆分问题
我是编程初学者,正在搭建TCP点对点聊天程序,需要把任务拆分到不同线程。打算给消息发送部分(Scanner、DataOutputStream等)单独开线程,所以实现了Runnable接口,但run()方法里没法调用socket的OutputStream对象,卡了一周,求解决思路。
原代码示例
public class ClientHorcher implements Runnable { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(11111); System.out.println("Waiting For Connection:- "); Socket socket = serverSocket.accept(); Scanner scanner = new Scanner(System.in); DataInputStream datenRein = new DataInputStream(socket.getInputStream()); DataOutputStream datenRaus = new DataOutputStream(socket.getOutputStream()); String nickname; System.out.print("Gib einen Nickname ein: "); nickname = scanner.nextLine(); while (true) { String vonMsg = datenRein.readUTF(); System.out.println("Client:- " + vonMsg); if (vonMsg.equals("exit")) { System.out.println("Beenden!!!"); datenRein.close(); datenRaus.close(); scanner.close(); socket.close(); serverSocket.close(); System.exit(0); } System.out.print(nickname + " :- "); String zuMsg = scanner.nextLine(); datenRaus.writeUTF(zuMsg); if (zuMsg.equals("exit")) { System.out.println("Quiting!!!"); datenRein.close(); datenRaus.close(); scanner.close(); socket.close(); serverSocket.close(); System.exit(0); } } } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { } } public class ClientVerbinder implements Runnable { public static void main(String[] args) { try { Socket socket = new Socket("Localhost", 11111); System.out.println("Connected"); Scanner scanner = new Scanner(System.in); DataInputStream datenRein = new DataInputStream(socket.getInputStream()); DataOutputStream datenRaus = new DataOutputStream(socket.getOutputStream()); String nickname; System.out.print("Gib einen Nickname ein: "); nickname = scanner.nextLine(); while (true) { System.out.print(nickname + " :- "); String zuMsg = scanner.nextLine(); datenRaus.writeUTF(zuMsg); if (zuMsg.equals("exit")) { System.out.println("Beenden!!!"); datenRein.close(); datenRaus.close(); scanner.close(); socket.close(); System.exit(0); } String vonMsg = datenRein.readUTF(); System.out.println("CLient" + " :- " + vonMsg); if (vonMsg.equals("exit")) { System.out.println("Quiting!!!"); datenRein.close(); datenRaus.close(); scanner.close(); socket.close(); System.exit(0); } } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { } }
解决思路
- 成员变量传递依赖:把Socket、DataOutputStream、Scanner等需要在run()中使用的对象,通过线程类的构造方法传入,作为类的成员变量,这样run()方法就能直接访问这些对象。
- 拆分读写线程:将消息读取和消息发送拆分为两个独立线程,避免单线程中读写操作互相阻塞导致程序无响应。
- 统一资源管理:不要在循环内重复关闭资源,编写统一的资源关闭方法,在程序退出或异常时调用,保证资源正确释放。
修改后的代码示例
ClientHorcher(服务端角色)
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class ClientHorcher { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(11111); System.out.println("等待连接..."); Socket socket = serverSocket.accept(); Scanner scanner = new Scanner(System.in); DataInputStream datenRein = new DataInputStream(socket.getInputStream()); DataOutputStream datenRaus = new DataOutputStream(socket.getOutputStream()); System.out.print("输入昵称: "); String nickname = scanner.nextLine(); // 启动读消息线程 Thread readThread = new Thread(new ReadRunnable(datenRein, socket, serverSocket, scanner, datenRaus)); // 启动写消息线程 Thread writeThread = new Thread(new WriteRunnable(datenRaus, scanner, nickname, socket, serverSocket, datenRein)); readThread.start(); writeThread.start(); } catch (IOException e) { e.printStackTrace(); } } // 读消息线程类 static class ReadRunnable implements Runnable { private DataInputStream datenRein; private Socket socket; private ServerSocket serverSocket; private Scanner scanner; private DataOutputStream datenRaus; public ReadRunnable(DataInputStream datenRein, Socket socket, ServerSocket serverSocket, Scanner scanner, DataOutputStream datenRaus) { this.datenRein = datenRein; this.socket = socket; this.serverSocket = serverSocket; this.scanner = scanner; this.datenRaus = datenRaus; } @Override public void run() { try { while (true) { String vonMsg = datenRein.readUTF(); System.out.println("对方: " + vonMsg); if (vonMsg.equals("exit")) { System.out.println("对方已退出,程序结束!"); closeResources(); System.exit(0); } } } catch (IOException e) { e.printStackTrace(); closeResources(); } } private void closeResources() { try { if (datenRein != null) datenRein.close(); if (datenRaus != null) datenRaus.close(); if (scanner != null) scanner.close(); if (socket != null) socket.close(); if (serverSocket != null) serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } // 写消息线程类 static class WriteRunnable implements Runnable { private DataOutputStream datenRaus; private Scanner scanner; private String nickname; private Socket socket; private ServerSocket serverSocket; private DataInputStream datenRein; public WriteRunnable(DataOutputStream datenRaus, Scanner scanner, String nickname, Socket socket, ServerSocket serverSocket, DataInputStream datenRein) { this.datenRaus = datenRaus; this.scanner = scanner; this.nickname = nickname; this.socket = socket; this.serverSocket = serverSocket; this.datenRein = datenRein; } @Override public void run() { try { while (true) { System.out.print(nickname + ": "); String zuMsg = scanner.nextLine(); datenRaus.writeUTF(zuMsg); if (zuMsg.equals("exit")) { System.out.println("已退出,程序结束!"); closeResources(); System.exit(0); } } } catch (IOException e) { e.printStackTrace(); closeResources(); } } private void closeResources() { try { if (datenRein != null) datenRein.close(); if (datenRaus != null) datenRaus.close(); if (scanner != null) scanner.close(); if (socket != null) socket.close(); if (serverSocket != null) serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
ClientVerbinder(客户端角色)
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; public class ClientVerbinder { public static void main(String[] args) { try { Socket socket = new Socket("localhost", 11111); System.out.println("已连接"); Scanner scanner = new Scanner(System.in); DataInputStream datenRein = new DataInputStream(socket.getInputStream()); DataOutputStream datenRaus = new DataOutputStream(socket.getOutputStream()); System.out.print("输入昵称: "); String nickname = scanner.nextLine(); // 启动读消息线程 Thread readThread = new Thread(new ReadRunnable(datenRein, socket, scanner, datenRaus)); // 启动写消息线程 Thread writeThread = new Thread(new WriteRunnable(datenRaus, scanner, nickname, socket, datenRein)); readThread.start(); writeThread.start(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // 读消息线程类 static class ReadRunnable implements Runnable { private DataInputStream datenRein; private Socket socket; private Scanner scanner; private DataOutputStream datenRaus; public ReadRunnable(DataInputStream datenRein, Socket socket, Scanner scanner, DataOutputStream datenRaus) { this.datenRein = datenRein; this.socket = socket; this.scanner = scanner; this.datenRaus = datenRaus; } @Override public void run() { try { while (true) { String vonMsg = datenRein.readUTF(); System.out.println("对方: " + vonMsg); if (vonMsg.equals("exit")) { System.out.println("对方已退出,程序结束!"); closeResources(); System.exit(0); } } } catch (IOException e) { e.printStackTrace(); closeResources(); } } private void closeResources() { try { if (datenRein != null) datenRein.close(); if (datenRaus != null) datenRaus.close(); if (scanner != null) scanner.close(); if (socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); } } } // 写消息线程类 static class WriteRunnable implements Runnable { private DataOutputStream datenRaus; private Scanner scanner; private String nickname; private Socket socket; private DataInputStream datenRein; public WriteRunnable(DataOutputStream datenRaus, Scanner scanner, String nickname, Socket socket, DataInputStream datenRein) { this.datenRaus = datenRaus; this.scanner = scanner; this.nickname = nickname; this.socket = socket; this.datenRein = datenRein; } @Override public void run() { try { while (true) { System.out.print(nickname + ": "); String zuMsg = scanner.nextLine(); datenRaus.writeUTF(zuMsg); if (zuMsg.equals("exit")) { System.out.println("已退出,程序结束!"); closeResources(); System.exit(0); } } } catch (IOException e) { e.printStackTrace(); closeResources(); } } private void closeResources() { try { if (datenRein != null) datenRein.close(); if (datenRaus != null) datenRaus.close(); if (scanner != null) scanner.close(); if (socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
内容的提问来源于stack exchange,提问作者Ljonja2107
相关产品推荐
相关产品推荐

