geo
geo

Reputation: 527

How to make thread wait untill method of another class completes

Here is my example code:

package javaapplication35;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import static javaapplication35.ProgressBarExample.customProgressBar;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

public class ProgressBarExample {

final static JButton myButton =new JButton("Start");
final static JProgressBar customProgressBar = new JProgressBar();
private static final JPanel myPanel = new JPanel();

public static void main(String[] args) {
    customProgressBar.setMaximum(32);
    customProgressBar.setStringPainted(true);
    myPanel.add(customProgressBar);
    myPanel.add(myButton);

    myButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e)
        {

            Thread firstly =new Thread(new Runnable (
            ) {
                @Override
                public void run() {
                    Calculations a = new  Calculations();
                    a.doCaculations();
                }
            });          

            Thread secondly =new Thread(new Runnable (
            ) {
                @Override
                public void run() {
                    JOptionPane.showMessageDialog(null,"just finished");
                }
            }); 

            firstly.start();
            try {
                firstly.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(ProgressBarExample.class.getName()).log(Level.SEVERE, null, ex);
            }


            secondly.start(); 
        }
    });          

    JOptionPane.showMessageDialog(null, myPanel, "Progress bar test", JOptionPane.PLAIN_MESSAGE);

 }

}

class Calculations {
public void doCaculations() {

     new SwingWorker<Void, Void>() {
        @Override
        protected Void doInBackground() throws Exception {
            int value = 0;
            while (value < customProgressBar.getMaximum()) {
                Thread.sleep(250);
                value ++;
                customProgressBar.setValue(value);
            }
            return null;
        }
    }.execute();
}   

 private void doOtherStaff(){
    //more methods, that don't need to run in seperate threads,  exist
 }

}

There are 2 Threads. The firstly thread creates a Calculations class insance and then runs a doCaculations() method on it. The secondly thread pops-up a message.

The doCaculations() method in my "real" code performs some time consuming maths and in order to simulate the time spent I added that Thread.sleep(250);. I need to inform the user on the progress of the calculations so I am using the progressbar, that is updated by the doCaculations() method.

I am trying to make the code work in a way that the secondly thread runs after the firstly thread finishes. But I cannot make it work. What happens is that the pop-up message pops-up immediately (and that means that it's thread run before I want it to run).

Note:The "just finished" message is there just to test the code. In my "real" program a method would be in it's place. I am making this note because if I just wanted a message to show I could just place it in the end of the doCaculations() method, and everything would work fine.

I know I must be doing wrong with the Thread handling but I cannot find it. Any ideas?

PS: A thought: Actually the doCaculations() method has its own thread. So it runs "in a SwingWorker inside a Thread". Iguess the firstly.join(); works correctly. But after the doCaculations() method is called the fistrly thread is considered finished, and that's why the code goes on with the secondly thread, not knowing that the doCaculations() thread is still doing something.

Upvotes: 0

Views: 1135

Answers (3)

qiGuar
qiGuar

Reputation: 1804

Try

a.doCaculations();
a.join();

edit:
Since you are using SwingWorker my previous answer is incorrect, but, as in you comment, you've extended Thread, the following should work for you:

Thread a = new Calculations();
a.start();
a.join();

Don't forget, that you have to override run method in Calculations class, like:

class Calculations extends Thread {
    @Override
    public void run() {
        //your code here
    }    
}

Upvotes: 2

Tactical Downvote
Tactical Downvote

Reputation: 2393

Your Calculations class must extend SwingWorker. You do your calculations in doInBackground()

public class Calculations extends SwingWorker<Void, Void>{

    @Override
    protected Void doInBackground() throws Exception {
        System.out.println("Calculating.");
        Thread.sleep(3000);
        return null;
    }
}   

And in your actionPerformed() you use Calculations like this.

    public void actionPerformed(ActionEvent e)
    {
      //FISRT run method
      Calculations a = new  Calculations();
      a.execute(); // Start calculations
      try {
        a.get(); // Wait for calculations to finish
      } catch (InterruptedException | ExecutionException e1) {
        e1.printStackTrace();
      }
      //THEN inform that just finished
      JOptionPane.showMessageDialog(null,"just finished");
    }

EDIT: If you have multiple methods that you would like to run in a SwingWorker you can keep your code almost like it is. But only add these lines.

public class Calculations{
    protected void calculate() {
        SwingWorker sw = new SwingWorker(){
            @Override
            protected Object doInBackground() throws Exception {
                System.out.println("Calculating.");
                Thread.sleep(3000);
                return null;
            }
        };
        sw.execute(); //Start
        try {
            sw.get(); //Wait
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

In each method of Calculations you create a new SwingWorker like you did and wait for it to finish by calling SwingWorker.get();

Upvotes: 1

Kevin Joymungol
Kevin Joymungol

Reputation: 1814

In java you can use swingworker and in the done() method call your Dialog

In android you can use AsyncTask for calling the new thread and in the OnPostExecute method, call show message dialog.

Upvotes: 2

Related Questions