Используя try с ресурсами в многопоточном сервере в Java - PullRequest
0 голосов
/ 16 октября 2018

Я читаю книгу «Java Networking 4th Edition» и в 9-й главе о серверных сокетах, в то время как объясняю многопоточный сервер, где каждый клиент обрабатывается одним потоком, он сказал следующее:

Пример 9-3 намеренно не использует try-with-resources для клиентских сокетов, принятых серверным сокетом.Это связано с тем, что клиентский сокет выходит из блока try в отдельный поток.Если вы используете try-with-resources, основной поток закроет сокет, как только он достигнет конца цикла while, вероятно, до того, как порожденный поток завершит его использование.

ВотПример 9-3

import java.net.*;
import java.io.*;
import java.util.Date;
public class MultithreadedDaytimeServer {
public final static int PORT = 13;
public static void main(String[] args) {
    try (ServerSocket server = new ServerSocket(PORT)) {
        while (true) {
            try {
                Socket connection = server.accept();
                Thread task = new DaytimeThread(connection);
                task.start();
            } catch (IOException ex) {}
        }
    } catch (IOException ex) {
        System.err.println("Couldn't start server");
    }
}
private static class DaytimeThread extends Thread {
    private Socket connection;
    DaytimeThread(Socket connection) {
        this.connection = connection;
    }
    @Override
    public void run() {
        try {
            Writer out = new OutputStreamWriter(connection.getOutputStream());
            Date now = new Date();
            out.write(now.toString() +"\r\n");
            out.flush();
        } catch (IOException ex) {
            System.err.println(ex);
        } finally {
            try {
                connection.close();
            } catch (IOException e) {
                // ignore;
            }
        }
    }
}

}

Я не очень понимаю, почему это происходит, почему основной поток хочет закрыть сокет из другого потока, потому что сокетобъект был создан в основном потоке, а ссылка была указана в конструкторе потока?

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Основной поток не хочет закрывать ресурс, потому что порожденный поток выполняется асинхронно .

В пределах try, task.start() начинает выполнение потока, но этоне ждет, пока это закончится.Следовательно, возможно (даже вероятно), что основной метод достигнет конца своих try до завершения DaytimeThread.run().

Если основной метод try был попыткой с ресурсами,соединение будет закрыто в это время.Затем, когда DaytimeThread продолжает выполнять свою работу в другом потоке, он попытается использовать это соединение после его закрытия.

Но чтобы ответить на ваш настоящий вопрос:

почему основной поток хочет закрыть сокет из другого потока

Это не сокет из другого потока.Фактически, метод main принимает подключение к сокету и затем передает его DaytimeThread.

Обычно , объекту, отвечающему за получение близкого ресурсатакже должен нести ответственность за его закрытие.Простой способ сделать это - попробовать с ресурсами.Тем не менее, этот принцип не может быть применен с этим дизайном, потому что поток может нуждаться в ресурсе после того, как основной поток закончил с ним.

0 голосов
/ 16 октября 2018

Книга говорит о том, что они решили сделать это

try {
    Socket connection = server.accept();
    Thread task = new DaytimeThread(connection);
    task.start();
} catch (IOException ex) {}

вместо

try(Socket connection = server.accept()) {
    Thread task = new DaytimeThread(connection);
    task.start();
} catch (IOException ex) {}

, потому что при использовании блока try-with-resources он закрывает все, что вы положили в скобки try(...) сразу после того, как это будет сделано.Но вы не хотите, чтобы это произошло.Сокет connection должен оставаться открытым, потому что он будет использоваться в DaytimeThread, который был запущен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...