如何使线程等到另一个类的方法完成

时间:2014-02-14 10:15:05

标签: java multithreading thread-synchronization

这是我的示例代码:

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
 }

}

有2个主题。 firstly线程创建Calculations类insance,然后在其上运行doCaculations()方法。 secondly线程会弹出一条消息。

我的“真实”代码中的doCaculations()方法会执行一些耗时的数学运算,并且为了模拟我添加Thread.sleep(250);所花费的时间。我需要告知用户计算的进度,以便我使用进度条,该进度条由doCaculations()方法更新。

我正在尝试使代码工作,secondly线程在firstly线程完成后运行。但我不能让它发挥作用。发生的事情是弹出消息立即弹出(这意味着它的线程在我希望它运行之前运行)。

注意:“刚完成”的消息只是为了测试代码。在我的“真实”程序中,一种方法就在它的位置。我正在做这个说明,因为如果我只想要一条消息来表明我可以将它放在doCaculations()方法的末尾,那么一切都会正常工作。

我知道我必须在线程处理方面做错,但我找不到它。有什么想法吗?

PS:一个想法:实际上doCaculations()方法有自己的主题。所以它在“线程内的SwingWorker”中运行。让firstly.join();正常工作。但是在调用doCaculations()方法之后,fistrly线程被认为已完成,这就是为什么代码继续使用secondly线程,而不知道doCaculations()线程仍然存在做某事。

3 个答案:

答案 0 :(得分:2)

尝试

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

修改
由于您使用的是SwingWorker,我之前的回答是不正确的,但是,正如在您的评论中,您已经扩展了Thread,以下内容对您有用:

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

不要忘记,您必须在计算类中覆盖run方法,例如:

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

答案 1 :(得分:2)

在java中你可以使用swingworker并在done()方法中调用你的Dialog

在android中你可以使用AsyncTask来调用新线程,在OnPostExecute方法中,调用show message dialog。

答案 2 :(得分:1)

您的Calculations类必须扩展SwingWorker。您可以在doInBackground()

中进行计算
public class Calculations extends SwingWorker<Void, Void>{

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

在你的actionPerformed()中,你使用像这样的计算。

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

编辑:如果您希望在SwingWorker中运行多种方法,则可以使代码保持原样。但只添加这些行。

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

Calculations的每种方法中,您就像创建一个新的SwingWorker一样,并通过调用SwingWorker.get();

等待它完成