我有一台具有多个客户端的服务器。它使用一个服务器套接字和两个线程池来接收和处理来自远程客户端的请求:一个池-用于处理客户端连接,另一个池-用于处理客户端远程任务。每个客户端发送具有唯一任务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();
}
}
}
我有一台具有多个客户端的服务器。它使用一个服务器套接字和两个线程池来接收和处理来自远程客户端的请求:一个池-用于处理客户端连接,而另一个...
根据经验:如果文档未指定某个类是线程安全的,则可能不是。线程安全性显然是一种“有意的质量”(是对Roman Elizarov's blog post的暗示,是Kotlin的语言设计师之一),因此应始终提及。
但是,如果您仍然不确定Java SE库的类是否提供线程安全(可能在其他地方提到,例如超类的文档),您也可以快速浏览一下类型的源代码。 As you can see,ObjectOutputStream
没有实现任何同步机制。
此here说得很好: