我有一个带有多个客户端的服务器。它使用一个服务器套接字和两个线程池来接收和处理来自远程客户端的请求:一个线程池 - 用于处理客户端连接,另一个线程池 - 用于处理客户端远程任务。每个客户端发送具有唯一任务 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说得好:
Is writing an object to an ObjectOutputStream a thread-safe operation?
Absolutely not.
所以,是的,您的代码本身需要采取预防措施。
关于java - 我应该同步 ObjectOutputStream.writeObject(Object) 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58970685/