У меня есть сервер с несколькими клиентами. Он использует один сокет сервера и два пула потоков для получения и обработки запросов от удаленных клиентов: один пул - для обработки клиентских подключений, а другой - для обработки удаленных задач клиентов. Каждый клиент отправляет асинхронные задачи с уникальным идентификатором задачи (в пределах каждого соединения) и набором параметров. После десериализации задачи сервер ищет соответствующую службу, вызывает для нее заданный метод, оборачивает результат вместе с идентификатором задачи в объект ответа и отправляет его обратно клиенту, используя 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();
}
}
}