简体   繁体   中英

Pause further execution if Thread has not finished

I have written a program which executes a cmd command and prints an output to the program's 'console'. I have used Thread to print the output without freezing the program. I want to be able to see live output.

What's wrong with it and I can't find a solution for it is that part in initialize right after executeCommand method is being called is being executed right after executeCommand. What I want to be able to do is execute the rest of the initialize once the thread has stopped running. I can't do it without freezing the whole program.

I have used Thread join method and similar but my app just freezes completely.

This is my main class

private String genCmd2;

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                ConvertGUI window = new ConvertGUI();
                window.frmConvert.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public ConvertGUI() {
    initialize();
}

private void initialize() {
     // Execute a generated command concurrently
    genCmd2 = "ping google.com -n 5";
    executeCommand(genCmd2, genCmdTextArea);

    //CODE TO RUN AFTER EXECUTE COMMAND IS FULLY FINISHED
    //NOT RIGHT AFTER executeCommand method is called

}

public static void printToTheConsole(JTextArea console, String message) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            console.append(message);
            console.validate();
        }
    });
}

private static void executeCommand(String command, JTextArea console) {
    Runnable r = new CommandLineRunnable(command, console);
    t = new Thread(r);
    t.start();
}

My Runnable class which executes a command and prints stuff to the console

public class CommandLineRunnable extends ConvertGUI implements Runnable {
    private String generatedCommand;
    private JTextArea console;

    public CommandLineRunnable(String command, JTextArea console) {
        this.generatedCommand = command;
        this.console = console;
        printToTheConsole(console, command);
    }

    @Override
    public void run() {
        StringBuilder output = new StringBuilder();
        BufferedReader reader;
        Process process;
        try {
            process = Runtime.getRuntime().exec(generatedCommand);
            reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;

            while ((line = reader.readLine()) != null) {
                output.append(line + "\n");
                printToTheConsole(console, line + "\n");
            }

            printToTheConsole(console, "\n--------------------------Success!--------------------------\n");

            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

If you want to print to the console, update a JTextArea during and after one of your Runnable# tasks has (un)successfully been executed, you could implement an interface and supply it to your Runnables constructor

Consider the following example which instantiates the CommandLineRunnable class with arguments String 'aCommand' as a command, fa JTextArea object 'console' and a new ResponseEvent anonymous class as its parameters.

Note, due to the duplication in the anonymous class, if you're executing multiple commands, it's likely you wouldn't want to instantiate the anonymous class multiple times and could just insert the printToTheConsole code inside of the Functional Interface's methods

    public static void main(String[] args) {

        JTextArea console = new JTextArea();

        /**
         * JTextArea init code here
         */

        executeCommand("aCommand", console, new ResponseEvent() {

            @Override
            public void onSuccess(JTextArea console, String response) {
                printToTheConsole(console, response);
            }

            @Override
            public void onUpdate(JTextArea console, String response) {
                printToTheConsole(console, response);
            }

            @Override
            public void onFailure(JTextArea console, String response) {
                printToTheConsole(console, response);
            }
        });
    }

    private static void printToTheConsole(JTextArea console, String message) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                console.append(message);
                console.validate();
            }
        });
    }

    private static void executeCommand(String command, JTextArea console, ResponseEvent event) {
        Runnable r = new CommandLineRunnable(command, console, event);
        Thread thread = new Thread(r);
        thread.start();
    }

    @FunctionalInterface
    private interface ResponseEvent {
        default void onSuccess(JTextArea console, String response) {

        }

        default void onUpdate(JTextArea console, String response) {

        }

        default void onFailure(JTextArea console, String response) {

        }

    }

    public static class CommandLineRunnable implements Runnable {

        private final String command;
        private final ResponseEvent event;
        private final JTextArea console;

        public CommandLineRunnable(String command, JTextArea console, ResponseEvent event) {
            this.command = command;
            this.console = console;
            this.event = event;
        }

        public ResponseEvent getEvent() {
            return event;
        }

        @Override
        public void run() {
            Process process;
            BufferedReader reader = null;
            try {
                process = Runtime.getRuntime().exec(getCommand());
                reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

                String line;

                while ((line = reader.readLine()) != null) {
                    getEvent().onUpdate(getConsole(), line + "\n");
                }

                getEvent().onSuccess(getConsole(), "\n--------------------------Success!--------------------------\n");
            } catch (IOException e) {
                getEvent().onFailure(getConsole(), "\n--------------------------Failure!--------------------------\n");
            }
        }

        private JTextArea getConsole() {
            return console;
        }

        private String getCommand() {
            return command;
        }
    }

Upon execution, which could be at whatever time, the Runnable#run() function will be executed.

The code will run and either the ResponseEvent#onSuccess method or the ResponseEvent#onFailure method will be called

You can then handle the responses however you want, perhaps by updating one of your JTextAreas

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM