如何重新设计java应用程序以在新线程中提供变量的另一个副本?
我正在编写套接字客户端服务器控制台应用程序。我想在服务器上启用standart用户输入,同时与客户端通信。为了实现这一点,我用接口IScanner、IPrinter替换了所有system.out.println和scanner.scan,并用CLIScanner/Printer和SocketReader/Printer实现它们 所有CLI操作都在扩展BaseDialog的类中,BaseDialog使用IScanner/Printer实现之一。下面是BaseDialog的代码如何重新设计java应用程序以在新线程中提供变量的另一个副本?,java,multithreading,oop,design-patterns,architecture,Java,Multithreading,Oop,Design Patterns,Architecture,我正在编写套接字客户端服务器控制台应用程序。我想在服务器上启用standart用户输入,同时与客户端通信。为了实现这一点,我用接口IScanner、IPrinter替换了所有system.out.println和scanner.scan,并用CLIScanner/Printer和SocketReader/Printer实现它们 所有CLI操作都在扩展BaseDialog的类中,BaseDialog使用IScanner/Printer实现之一。下面是BaseDialog的代码 public abs
public abstract class BaseDialog {
public static IPrinter printer;
public static IScanner scanner;
static {
printer = CommunicationProvider.printer;
scanner = CommunicationProvider.scanner;
}
public BaseDialog() {
}
public BaseDialog(IPrinter printer, IScanner scanner) {
this.printer = printer;
this.scanner = scanner;
}
public static void done() {
printer.println("Done.");
}
public static void printOnExit() {
printer.println("Shutting down...");
printer.println("Finish");
}
public static void startMessage() {
printer.println("Application has started");
}
}
我有一些扩展BaseDialog的类,下面是一个示例
public class HelpDialog extends BaseDialog {
public static void printCommands(String[] commands) {
for(String command : commands) {
printer.println("\t " + command);
}
}
public static void commandsBelongs(String owner) {
printer.println("Commands for " + owner);
}
}
所有打印机方法以及IPrinter和IScanner实例都是静态的
使用多线程的想法-每个线程将使用自己的打印机或扫描仪,因此这是主启动类的代码:
public class Main {
final int portNumber = 3000;
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchAlgorithmException, IOException, InstantiationException, NoSuchMethodException, NoSuchFieldException {
BaseDialog.startMessage();
new CommandParser().Run();
}
private void startServer() throws IOException {
ServerSocket serverSocket = new ServerSocket(portNumber);
while(true) {
Socket connectionSocket = serverSocket.accept();
PrintWriter printWriter = new PrintWriter(connectionSocket.getOutputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
Thread thread = new Thread(() -> {
BaseDialog.scanner = new SocketReader(bufferedReader);
BaseDialog.printer = new SocketWriter(printWriter);
try {
new CommandParser().Run();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
});
thread.start();
}
}
}
问题就在这里
BaseDialog.scanner = new SocketReader(bufferedReader);
BaseDialog.printer = new SocketWriter(printWriter);
所有线程都使用相同的scanner和printer实例,但我需要每个线程都有自己的scanner和printer实例。因为每个扫描仪和打印机与不同的客户机一起工作
我曾经考虑过将对话类声明为使用它们的类的字段,但是使用对话的类太多了。我真的不想支持这个解决方案,而是更愿意在全球范围内提供实例
如何重新设计应用程序以为每个线程提供自己的打印机和扫描仪实例?很简单:您的扫描仪和打印机是静态的,这意味着它们不绑定到BaseDialog对象,而是每个JVM只有一个引用。删除
static
关键字,就可以开始了
如果绝对<强>必须< /强>是静态的(在这种情况下,我会考虑设计缺陷),可以考虑使用TreLeaTea:
不幸的是,您可能必须将这些读写器设置为某个对象的字段。