You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在多线程Java服务器中向客户端发送ArrayList?

解决多线程服务器向客户端传输ArrayList的问题

要在Java Socket通信中传输ArrayList,核心是利用对象序列化——把Java对象转换成字节流在网络中传输,另一端再把字节流还原成对象。下面是具体实现步骤和修改后的代码:

前置准备:确保元素可序列化

ArrayList本身实现了Serializable接口,但它里面的元素也必须实现该接口,否则会抛出NotSerializableException。比如你要传输酒店数据,先定义一个可序列化的实体类:

import java.io.Serializable;

public class Hotel implements Serializable {
    // 建议显式声明序列化版本号,避免版本不一致问题
    private static final long serialVersionUID = 1L;
    private String name;
    private String address;

    public Hotel(String name, String address) {
        this.name = name;
        this.address = address;
    }

    @Override
    public String toString() {
        return "酒店名称:" + name + ",地址:" + address;
    }
}

修改服务器代码

替换原有的字符流为对象流,添加触发传输ArrayList的逻辑(比如客户端发送getList指令时发送),同时修正原代码中的语法错误:

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Collections;

class Server {
    // 用Collections.synchronizedList保证多线程环境下的线程安全
    private static final ArrayList<Object> objList = Collections.synchronizedList(new ArrayList<>());

    public static void main(String[] args) {
        // 初始化测试数据
        objList.add(new Hotel("万豪酒店", "北京朝阳区"));
        objList.add(new Hotel("希尔顿酒店", "上海黄浦区"));

        ServerSocket server = null;
        try {
            server = new ServerSocket(1234);
            server.setReuseAddress(true);

            while (true) {
                Socket client = server.accept();
                System.out.println("新客户端连接:" + client.getInetAddress().getHostAddress());
                new Thread(new ClientHandler(client)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (server != null) {
                try {
                    server.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 保留原文件读取方法,可自行修改为将文件内容转为对象加入objList
    private static String Read_File(String filePath) {
        StringBuilder builder = new StringBuilder();
        try (BufferedReader buffer = new BufferedReader(new FileReader(filePath))) {
            String str;
            while ((str = buffer.readLine()) != null) {
                builder.append(str).append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return builder.toString();
    }

    private static class ClientHandler implements Runnable {
        private final Socket clientSocket;

        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }

        public void run() {
            ObjectOutputStream out = null;
            ObjectInputStream in = null;
            try {
                // 注意:必须先创建ObjectOutputStream,再创建ObjectInputStream,否则会阻塞
                out = new ObjectOutputStream(clientSocket.getOutputStream());
                in = new ObjectInputStream(clientSocket.getInputStream());

                String line;
                while ((line = (String) in.readObject()) != null) {
                    System.out.printf("客户端发送:%s\n", line);
                    if ("getList".equalsIgnoreCase(line)) {
                        // 发送ArrayList对象
                        out.writeObject(objList);
                        out.flush();
                        System.out.println("已向客户端发送ArrayList");
                    } else {
                        // 原回显逻辑
                        out.writeObject("服务器回复:" + line);
                        out.flush();
                    }
                }
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null) out.close();
                    if (in != null) in.close();
                    clientSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

修改客户端代码

同样替换为对象流,处理服务器返回的ArrayList:

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Scanner;

class Client {
    public static void main(String[] args) {
        try (Socket socket = new Socket("localhost", 1234)) {
            ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

            Scanner sc = new Scanner(System.in);
            String line = null;

            while (!"exit".equalsIgnoreCase(line)) {
                line = sc.nextLine();
                out.writeObject(line);
                out.flush();

                // 读取服务器返回的对象
                Object response = in.readObject();
                if (response instanceof ArrayList) {
                    System.out.println("收到服务器的ArrayList:");
                    ArrayList<?> list = (ArrayList<?>) response;
                    for (Object item : list) {
                        System.out.println(item);
                    }
                } else {
                    System.out.println(response);
                }
            }
            sc.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

关键注意事项

  • 所有要传输的对象(包括ArrayList中的元素)必须实现Serializable接口。
  • 流的创建顺序:服务器和客户端都要先创建ObjectOutputStream,再创建ObjectInputStream,否则会因等待对方的流头而阻塞。
  • 多线程环境下,共享的ArrayList要保证线程安全,使用Collections.synchronizedList或CopyOnWriteArrayList。
  • 可以通过自定义指令(如getList)触发服务器发送ArrayList,避免不必要的传输。

内容的提问来源于stack exchange,提问作者Fiordi Toska

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 10:46:20