我有一台具有多个客户端的服务器。它使用一个服务器套接字和两个线程池来接收和处理来自远程客户端的请求:一个池-用于处理客户端连接,另一个池-用于处理客户端远程任务。每个客户端发送具有唯一任务ID(在每个连接中)和一堆参数的异步任务。任务反序列化后,服务器将查找相应的服务,在其上调用给定的方法,将结果与任务ID一起包装到答案对象中,然后使用ObjectOutputStream将其发送回客户端。

由于任务是同时处理的,因此两个或多个线程可能同时完成一个客户端的任务处理,并尝试竞争ObjectOutputStream

接下来发生什么?我的意思是说,他们是将对象写入原子以输出流,还是应该同步他们对ObjectOutputStream的访问,以避免出现这样的情况:当一个线程写入其对象的一半时,另一个线程进行干预,因此...某种科学怪人对象将被发送到客户端。

import java.io.*;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.*;

public class Server {

    private final ExecutorService connExecutor = Executors.newCachedThreadPool();
    private final ExecutorService tasksExecutor = Executors.newCachedThreadPool();

    public void start() {
        try (ServerSocket socket = new ServerSocket(2323);) {
            while (true) {
                try (Socket conn = socket.accept()) {
                    connExecutor.execute(() -> {
                        try (ObjectInputStream in = new ObjectInputStream(conn.getInputStream());
                             ObjectOutputStream out = new ObjectOutputStream(conn.getOutputStream())) {
                            while (true) {
                                RemoteTask task = (RemoteTask) in.readObject();
                                tasksExecutor.execute(() -> {
                                    handleTask(task, out);
                                });
                            }
                        } catch (IOException | ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                    });
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void handleTask(RemoteTask task, ObjectOutputStream out) {
        RemoteAnswer answer = new RemoteAnswer();
        // unwrap remote task
        // lookup local service
        // invoke task's method
        // wrap result into remote answer

        // send answer to the client
        try {
            out.writeObject(answer);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

最佳答案

这个here很好的说:


  将对象写入ObjectOutputStream是线程安全的操作吗?
  
  绝对不。


因此,是的,您的代码本身需要采取预防措施。

关于java - 我应该同步ObjectOutputStream.writeObject(Object)吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58970685/

10-11 16:35