javaswingswingworker

Execute process in Java without JFrame freezing


how can I execute a process in Java without the program freezing? I've tried using SwingWorker, but I don't quite yet understand how it works.

Is there any other way I can accomplish this?

Thanks in advance!

EDIT:

Thanks for your answers. But I have a class with several methods (well, it's more than one class, but you get my point); how can I use a SwingWorker to interact with those?

Here is one of the classes:

/**
 *
 * @author Simon
 */
    public abstract class Command extends SwingWorker {

    BufferedReader prReader = null;
    ProcessBuilder process = null;
    Process pr = null;
    Date timeNow = new Date();
    String osName = System.getProperty("os.name");

    public void executeProcessNoReturn(String _process, String arg) throws IOException {
        process = new ProcessBuilder(_process, arg);
        pr = process.start();
    }

     public String executeProcessReturnLastLine(String _process, String arg) throws IOException {
        process = new ProcessBuilder(_process, arg);
        pr = process.start();
        prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
        String line;
        while ((line = prReader.readLine()) != null) {
            // Wait for input to end.
        }
        return line;
    }

    public StringBuilder executeProcessReturnAllOutput(String _process, String arg) throws IOException {
        process = new ProcessBuilder(_process, arg);
        pr = process.start();
        prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
        StringBuilder output = null;
        String line;
        while ((line = prReader.readLine()) != null) {
            output.append(line);
        }
        return output;
    }

    public boolean isProcessRunning(String processName) throws IOException {
        boolean value = false;
        if (osName.equals("Linux") | osName.contains("Mac")) {
            process = new ProcessBuilder("ps", "-e");
            pr = process.start();
            String line;
            prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
            while ((line = prReader.readLine()) != null) {
                if (line.contains(processName)) { value = true; break; }
            }
        } else {
            String winDir = System.getenv("windir") + "/System32/tasklist.exe";
            process = new ProcessBuilder(winDir);
            pr = process.start();
            String line;
            prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
            while ((line = prReader.readLine()) != null) {
            if (line.contains(processName)) { value = true; break; }
            }
        }
    
        return value;
     
    }

     public String executeProcessReturnError(String processName, String arg) throws IOException {
        process = new ProcessBuilder(processName, arg);
        process.redirectError();
        pr = process.start();
        prReader = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
        String line;
        String output = "";
        while ((line = prReader.readLine()) != null) {
        output += line + "\n";
        }
        return output;
    }
}

Solution

  • Yes you can use a SwingWorker the idea is that a task that takes a lot of time you run in a separate thread (background thread) then you don't block your gui and your JFrame is not gonna to freeze. Here is a complete example i really like Swing Worker Example.

    Basically as an example you create your own class that extends SwingWorker override doInBackground.

    NOTE: You can have fields like a normal class.

    Example :

    class Worker extends SwingWorker<Void, String> {
        private SomeClass businessDelegate;    
        private JLabel label;
    
        @Override
        protected Void doInBackground() throws Exception {
           //here you make heavy task this is running in another thread not in EDT
            businessDelegate.callSomeService();
            setProgress(30); // this is if you want to use with a progressBar
            businessDelegate.saveToSomeDataBase();
            publish("Processes where saved");
            return null;
        }
    
        @Override
        protected void process(List<String> chunks){
           //this is executed in EDT you can update a label for example
           label.setText(chunks.toString());
        }
    
       //add setters for label and businessDelegate    
    }
    

    You also read about process(..) publish(..) and done().

    And in your client code just put.

    SwingWorker<Void,String> myWorker = new Worker();
    myWorker.execute();