3

I am currently building a small swing app to format drives and change permission and perform a bunch of small other things

Currently, I've come across an issue where running multiple processes will cause them to run asynchronously, which is awesome because it allows for me to dispatch a ton of processes quickly but for what I'm doing I need the process to wait for the one before it to finish.

The problem I've encountered is that the process.waitFor() method delays the GUI from being able to do anything (swing) until all of the processes are finished.

I'm currently using the following code structure (Which I've implemented from this answer) to deploy my commands/processes.

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

class RunSynchronously{
    private static final String sudoPassword = "1234";

    public static void main(String[] args) {
        Process process = null;
        String[] firstCmd = {"/bin/bash", "-c", "echo " + sudoPassword + "| sudo -S chmod 777 -R /media/myuser/mydrive"};
        try {
            process = Runtime.getRuntime().exec(firstCmd);
        } catch (IOException ex) {
            Logger.getLogger(Wizard_Home.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            process.waitFor();
        } catch (InterruptedException ex) {
            Logger.getLogger(Wizard_Format.class.getName()).log(Level.SEVERE, null, ex);
        }

        String[] secondCmd = {"/bin/bash", "-c", "echo " + sudoPassword + "| sudo -S chmod 755 -R /media/myuser/mydrive"};
        try {
            process = Runtime.getRuntime().exec(secondCmd);
        } catch (IOException ex) {
            Logger.getLogger(Wizard_Home.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            process.waitFor();
        } catch (InterruptedException ex) {
            Logger.getLogger(Wizard_Format.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

How can I delay processes or create a queue while maintaining my GUI as active and not slept/waiting?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Tyler
  • 73
  • 8

2 Answers2

4

How can I delay processes or create a queue while maintaining my GUI as active and not slept/waiting?

Use a SwingWorker so the processes execute in a separate Thread.

Read the section from the Swing tutorial on Concurrency for more information and working examples.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thank you for the suggestion, I'll take a look at those tutorials over the weekend and give it a shot to see if it helps my situation :) – Tyler Apr 28 '17 at 20:24
3
ExecutorService executor = Executors.newSingleThreadExecutor();
...
executor.execute(() -> yourLongRunningMethod());

The idea is that you create some executor that uses a different thread for execution and execute your heavy task in this thread. In my example, a single-thread executor is used. This will allow you to only pass a minimum amount of time in your GUI thread (task enqueueing is fast).

Please note that using this method you will have at least two threads: a GUI thread and an executor thread. They will probably have to communicate somehow (for example, to display work results in the GUI), so they will probably have to modify some shared data. Here, you may need some synchronization (due to concurrency).

Roman Puchkovskiy
  • 11,415
  • 5
  • 36
  • 72
  • Thank you for the suggestion, I'll look more into what you've recommended to do over this weekend to see if it helps my situation :) – Tyler Apr 28 '17 at 20:26
  • 1
    `for example, to display work results in the GUI)` - which is why you should use a `SwingWorker`. The SwingWorker has an API that allows you to "publish" results or execute code when the task is finished. This code will be executed on the EDT. – camickr May 09 '17 at 16:10