У меня есть класс MesssageReader
, который читает сообщения из потока в отдельном потоке. Теперь, когда я впервые создал решение, я создал объект потока за пределами класса потока, а затем передал его как ссылку на класс MessageReader
. Я передаю его через свой пользовательский интерфейс, так как в какой-то момент я хочу, возможно, изменить класс чтения потока. Поток читателя изящно заканчивается, если он получает специальное сообщение, указывающее конец потока сообщений. Основной поток, создавший поток, закрывает его. Теперь, моя забота о том, что это плохой дизайн? Поскольку, если я создаю поток за пределами чтения, кто-то другой может закрыть его, и это может вызвать проблемы. Но, с другой стороны, я создал сокет также вне потока читателей, что имеет смысл? так как вы могли бы создать больше потоков, которые читают сообщения из одного и того же соединения. Лучше ли создавать желаемый поток за пределами потока читателя или внутри, и пусть поток обрабатывает открытие и закрытие потока (но все же есть гибкость в создании различных вариантов/объектов потока)? Вот мой пример класс:Хорошо ли передавать открытые ресурсы в потоки?
public class MessageReader implements Runnable {
private MessageInputReader reader;
/* Custom interface for reading messages */
public MessageReader(MessageInputReader reader) {
this.reader = reader;
}
public void run() {
String line = null;
try {
while ((line = reader.readMessage()) != null) {
if ("BYE".equals(line)) {
break;
}
System.out.println(line);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
public class ReaderExample {
public static void main(String[] args) {
Socket clientSocket = null;
MessageBufferStream bufferedStream = null;
MessageReader reader;
try {
clientSocket = new Socket("hostname", 4060);
bufferedStream = new MessageBufferStream(clientSocket);
reader = new MessageReader(bufferedStream);
(new Thread(reader)).start();
someBlockingMethodWhichDoesOtherWork();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedStream != null)
bufferedStream.closeStream();
if (clientSocket != null)
clientSocket.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
}
А вот второй вариант:
public class MessageReader implements Runnable {
private MessageBufferStream reader;
public MessageReader(Socket clientSocket) throws IOException {
/* I could probably create a factory method here which would
* return different stream objects and achieve the same flexibility as in the first example? */
this.reader = new MessageBufferStream(clientSocket);
}
public void run() {
String line = null;
try {
while ((line = reader.readMessage()) != null) {
if ("BYE".equals(line)) {
break;
}
System.out.println(line);
}
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
try {
if (reader != null)
reader.closeStream();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
А вот остальная часть кода:
public interface MessageInputStream {
public String readMessage() throws IOException;
public void closeStream() throws IOException;
}
public class MessageBufferStream implements MessageInputStream {
private BufferedReader reader;
public MessageBufferStream(Socket clientSocket) throws IOException {
this.reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
@Override
public String readMessage() throws IOException {
return reader.readLine();
}
@Override
public void closeStream() throws IOException {
reader.close();
}
}
Я не уверен, что существует установленная практика так или иначе. Я бы предпочел, чтобы рабочий поток выполнял всю работу, включая открытие нового потока, так что любые сообщения об ошибках приходят с одного места. личные предпочтения и довольно спекулятивные тоже. – markspace
Я думаю, что второй вариант был бы хорошим, поскольку один объект контролирует ресурс, но это тоже мое мнение. J ust хотел знать, существует ли обычная практика для подобных ситуаций. –