vendredi 24 novembre 2017

How to redesign java application to provide another copy of variable in the new thread?

I'm writing socket client-server console application. I want to enable standart user input on the server and at the same time to communicate with clients. To achieve this all system.out.println, and scanner.scan, I've replaced with interfaces IScanner, IPrinter and implement them with CLIScanner/Printer and SocketReader/Printer.

All CLI actions are in classes that extends BaseDialog, which use one of IScanner/Printer implementations. Here the code of BaseDialog.

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");
    }
}

I have some classes that are extends BaseDialog and here is example.

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);
    }
}

All printer methods are static as well as IPrinter and IScanner instances.

Idea to use multithreading - each thread will use own printer or scanner, so this is code of the main start up class:

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();
        }

    }
}

The problem is here

 BaseDialog.scanner = new SocketReader(bufferedReader);
 BaseDialog.printer = new SocketWriter(printWriter);

All threads use the same instance of scanner and printer, but I need for each thread their own instances scanner and printer. Because each scanner and printer work with different clients.

I've thought about declaring dialog classes as fields of classes that use them, but there are too many classes that use dialogs. I really don't wont to support this solution and prefer to the provide instances globally.

How to redesign application to provide for each thread own instances of printer and scanner?

Aucun commentaire:

Enregistrer un commentaire