等待后台进程以不同类的SwingWorker结束

我正在将文件导入项目,一旦用户单击选择此文件,我会做一些事情,包括通过命令行。

我用这种方法完成了它:

p = Runtime.getRuntime().exec(command, null, new File(directory)); p.waitFor(); 

由于此过程可能需要一些时间,因此我决定在新框架中显示一个进度条弹出窗口,显示当前进程的所有输出。 我跟随@trashgod的代码改编为我的项目。 出于这个问题的目的,让我说我完全按照原样。

我只是想在命令工作时出现这个窗口,然后关闭它自己。 我可以通过从override done方法处理帧来完成此操作。

我的问题是我正在从其他类创建这个类,而在执行它时,它继续使用代码。 例如:

  method1(); method2(); new SwingWorkerExample().displayGUI(); //Process continues in background method3(); 

这里我的method3()正在SwingWorkerExample类的进程完成之前执行。 我该怎么解决这个问题?

我已经尝试过放在displayGUI方法的末尾了:

 while(!backgroundTask.isDone()){ //do nothing } 

但它使整个框架不起作用或者可能冻结它。 我还尝试在backgrandtask类中创建pa全局变量后编写一个方法:

 public Process getProcess(){ return p; } 

然后从displaGUI()调用以下内容:

 backgroundTask.getProcess().waitFor(); 

但它返回一个空指针exception。

在显示命令窗口的输出时,我还能做什么来等待进程结束?

谢谢。 更新:这是链接代码的副本,其中包含一些更改以显示我的意思。 我不希望在进程完成之前打印第二个文本:

 package mcve; import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.event.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import javax.swing.*; /** * @se https://stackoverflow.com/a/20603012/230513 * @see https://stackoverflow.com/a/17763395/230513 * @seehttps://stackoverflow.com/questions/20600721/ */ public class SwingWorkerExample { private JFrame frame; private final JLabel statusLabel = new JLabel("Status: ", JLabel.CENTER); private final JTextArea textArea = new JTextArea(20, 20); private JButton startButton = new JButton("Start"); private JButton stopButton = new JButton("Stop"); private JProgressBar bar = new JProgressBar(); private BackgroundTask backgroundTask; private final ActionListener buttonActions = new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { JButton source = (JButton) ae.getSource(); if (source == startButton) { textArea.setText(null); startButton.setEnabled(false); stopButton.setEnabled(true); backgroundTask = new BackgroundTask(); backgroundTask.execute(); bar.setIndeterminate(true); } else if (source == stopButton) { backgroundTask.cancel(true); backgroundTask.done(); } } }; private void displayGUI() { frame = new JFrame("Swing Worker Example"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); JPanel panel = new JPanel(); panel.setBorder( BorderFactory.createEmptyBorder(5, 5, 5, 5)); panel.setLayout(new BorderLayout(5, 5)); JScrollPane sp = new JScrollPane(); sp.setBorder(BorderFactory.createTitledBorder("Output: ")); sp.setViewportView(textArea); startButton.addActionListener(buttonActions); stopButton.setEnabled(false); stopButton.addActionListener(buttonActions); JPanel buttonPanel = new JPanel(); buttonPanel.add(startButton); buttonPanel.add(stopButton); buttonPanel.add(bar); panel.add(statusLabel, BorderLayout.PAGE_START); panel.add(sp, BorderLayout.CENTER); panel.add(buttonPanel, BorderLayout.PAGE_END); frame.setContentPane(panel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } private class BackgroundTask extends SwingWorker { private int status; public BackgroundTask() { statusLabel.setText((this.getState()).toString()); } @Override protected Integer doInBackground() { try { ProcessBuilder pb = new ProcessBuilder("ping", "-c", "5","google.com");//change -c for -n in windows pb.redirectErrorStream(true); Process p = pb.start(); String s; BufferedReader stdout = new BufferedReader( new InputStreamReader(p.getInputStream())); while ((s = stdout.readLine()) != null && !isCancelled()) { publish(s); } if (!isCancelled()) { status = p.waitFor(); } p.getInputStream().close(); p.getOutputStream().close(); p.getErrorStream().close(); p.destroy(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(System.err); } return status; } @Override protected void process(java.util.List messages) { statusLabel.setText((this.getState()).toString()); for (String message : messages) { textArea.append(message + "\n"); } } @Override protected void done() { statusLabel.setText((this.getState()).toString() + " " + status); stopButton.setEnabled(false); startButton.setEnabled(true); bar.setIndeterminate(false); frame.dispose(); } } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { System.out.println("Here I start"); new SwingWorkerExample().displayGUI(); System.out.println("I'll show up when the SwingWorkerExample has finnished"); } }); } 

Update2 :我也尝试将进程放在main方法(displayGUI)中并发送对进程的引用但它不起作用,窗口只是冻结而不显示:

 frame.setVisible(true); bar.setIndeterminate(true); try { ProcessBuilder pb = new ProcessBuilder("ping", "-c", "20", "google.com"); pb.redirectErrorStream(true); Process p; p = pb.start(); backgroundTask = new BackgroundTask(p); backgroundTask.execute(); p.waitFor(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(System.err); } 

更新3 :关注@Hovercraft完整的Eals回答我最终得到了这个,这仍然无法正常工作,因为字符串出现在流程结束之前。 也许我已经理解它错了,或者它只是在这种情况下不起作用:

 package mcve; import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import javax.swing.*; import static javax.swing.Action.MNEMONIC_KEY; public class SwingWorkerExample { private JFrame frame; private ExecuteFrame backgroundTask; private class properyListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { // the above percolates from the SwingWorker to the containing // JPanel if (evt.getNewValue() == SwingWorker.StateValue.DONE) { int processState = backgroundTask.getProcessStatus(); System.out.println("Process State: " + processState + "\n"); } } } private void displayGUI() { frame = new JFrame("Swing Worker Example"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); backgroundTask = new ExecuteFrame(); frame.add(backgroundTask); backgroundTask.addPropertyChangeListener(new properyListener()); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); backgroundTask.startProcess(); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { System.out.println("Here I start"); SwingUtilities.invokeLater(() -> new SwingWorkerExample().displayGUI()); System.out.println("I'll show up when the SwingWorkerExample has finnished"); } }); } } @SuppressWarnings("serial") class ExecuteFrame extends JPanel { private final JLabel statusLabel = new JLabel("Status: ", JLabel.CENTER); private final JTextArea textArea = new JTextArea(20, 30); private StartAction startAction = new StartAction("Start", KeyEvent.VK_S); private StopAction stopAction = new StopAction("Stop", KeyEvent.VK_T); private JProgressBar bar = new JProgressBar(); private BackgroundTask backgroundTask; private int processStatus; public ExecuteFrame() { setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); setLayout(new BorderLayout(5, 5)); textArea.setFocusable(false); JScrollPane sp = new JScrollPane(); sp.setBorder(BorderFactory.createTitledBorder("Output: ")); sp.setViewportView(textArea); stopAction.setEnabled(false); JPanel buttonPanel = new JPanel(); buttonPanel.add(new JButton(startAction)); buttonPanel.add(new JButton(stopAction)); buttonPanel.add(bar); add(statusLabel, BorderLayout.PAGE_START); add(sp, BorderLayout.CENTER); add(buttonPanel, BorderLayout.PAGE_END); } public void startProcess() { if (backgroundTask != null && !backgroundTask.isDone()) { return; // background task not yet done } textArea.setText(""); startAction.setEnabled(false); stopAction.setEnabled(true); backgroundTask = new BackgroundTask(); backgroundTask.addPropertyChangeListener(new BGTaskListener()); backgroundTask.execute(); bar.setIndeterminate(true); } public void cancelProcess() { if (backgroundTask != null && !backgroundTask.isDone()) { backgroundTask.cancel(true); } } public void processStopped() { statusLabel.setText((backgroundTask.getState()).toString() + " " + processStatus); stopAction.setEnabled(false); startAction.setEnabled(true); bar.setIndeterminate(false); // Window thisWindow = SwingUtilities.getWindowAncestor(textArea); // thisWindow.dispose(); } public int getProcessStatus() { return processStatus; } public class BGTaskListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue() == SwingWorker.StateValue.DONE) { processStopped(); } // percolate this listener up to the main JPanel's Prop Chng // Listener ExecuteFrame.this.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); } } private class BackgroundTask extends SwingWorker { @Override protected Integer doInBackground() throws Exception { List list = new ArrayList(); list.add("ping"); String name = System.getProperty("os.name"); if (name.startsWith("Win")) { list.add("-n"); } else { list.add("-c"); } list.add("5"); list.add("google.com"); try { ProcessBuilder pb = new ProcessBuilder(list); pb.redirectErrorStream(true); Process p = pb.start(); String s; BufferedReader stdout = new BufferedReader( new InputStreamReader(p.getInputStream())); while ((s = stdout.readLine()) != null && !isCancelled()) { publish(s); } if (!isCancelled()) { processStatus = p.waitFor(); } p.getInputStream().close(); p.getOutputStream().close(); p.getErrorStream().close(); p.destroy(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(System.err); } return processStatus; } @Override protected void process(java.util.List messages) { statusLabel.setText((this.getState()).toString()); for (String message : messages) { textArea.append(message + "\n"); } } } private class StartAction extends AbstractAction { public StartAction(String name, int mnemonic) { super(name); putValue(MNEMONIC_KEY, mnemonic); } @Override public void actionPerformed(ActionEvent e) { startProcess(); } } private class StopAction extends AbstractAction { public StopAction(String name, int mnemonic) { super(name); putValue(MNEMONIC_KEY, mnemonic); } @Override public void actionPerformed(ActionEvent e) { cancelProcess(); } } } 

输出是:

 Here I start I'll show up when the SwingWorkerExample has finnished Process State: 0 

代替:

 Here I start Process State: 0 I'll show up when the SwingWorkerExample has finnished 

最好的解决方案是将一个PropertyChangeListener添加到SwingWorker中,并在其回调方法中检查要结束的进程。 这将允许您的Swing事件线程运行,并将在工作完成时在Swing事件线程上通知您。 您甚至可以侦听worker的progress属性的更改,并从此侦听器中更改JProgressBar。 例如(代码未测试):

 private class TaskListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { SwingWorker task = (SwingWorker) evt.getSource(); // here we can listen for changes to the worker's progress property // if we desire if ("progress".equals(evt.getPropertyName())) { int progress = task.getProgress(); progressBar.setValue(progress); } // listen for the worker to be done if (SwingWorker.StateValue.DONE == evt.getNewValue()) { // always need to know when the SW is done // so we can call get() and trap exceptions try { task.get(); // do something with the result returned? // !! here do things that you want done when the SwingWorker has completed *** } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } } } 

别处…

 MySwingWorker myWorker = new MySwingWorker(); myWorker.addPropertyChangeListener(new TaskListener()); myWorker.execute(); 

关于:

在显示命令窗口的输出时,我还能做什么来等待进程结束?

获取和显示命令窗口输出是一个完全不同的问题,并且需要从正在运行的后台进程中获取InputStream。


编辑我正在玩这个,代码显示两个窗口,第二个执行swing工作,第一个侦听JPanel上的属性更改是第二个的一部分,但它不是很干净的代码,因为它没有很好的MVC关注点分离:

 import java.awt.BorderLayout; import java.awt.Dialog.ModalityType; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import javax.swing.*; public class SwingWorkerExample2 { private static void createAndShowGui() { SWEx2MainPanel mainPanel = new SWEx2MainPanel(); JFrame frame = new JFrame("SwingWorker Example"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> createAndShowGui()); } } @SuppressWarnings("serial") class SWEx2MainPanel extends JPanel { public static final ModalityType DLG_MODALITY_TYPE = ModalityType.MODELESS; private JTextArea statusArea = new JTextArea(15, 30); private JDialog workerDialog; private SWEx2WorkerPanel workerPanel = new SWEx2WorkerPanel(); public SWEx2MainPanel() { JPanel buttonPanel = new JPanel(); buttonPanel.add(new JButton(new ShowWorkerDialogAction())); statusArea.setFocusable(false); JScrollPane scrollPane = new JScrollPane(statusArea); scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); setLayout(new BorderLayout(5, 5)); add(scrollPane); add(buttonPanel, BorderLayout.PAGE_END); workerPanel.addPropertyChangeListener(new WorkerPanelListener()); } private class WorkerPanelListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { // the above percolates from the SwingWorker to the containing // JPanel if (evt.getNewValue() == SwingWorker.StateValue.DONE) { int processState = workerPanel.getProcessStatus(); statusArea.append("Process State: " + processState + "\n"); } } } private class ShowWorkerDialogAction extends AbstractAction { public ShowWorkerDialogAction() { super("Show Worker"); putValue(MNEMONIC_KEY, KeyEvent.VK_S); } @Override public void actionPerformed(ActionEvent e) { if (workerDialog == null) { Window window = SwingUtilities.getWindowAncestor(statusArea); workerDialog = new JDialog(window, "Worker Dialog", DLG_MODALITY_TYPE); workerDialog.add(workerPanel); workerDialog.pack(); workerDialog.setLocationByPlatform(true); } else if (workerDialog.isVisible()) { // dialog is still visible -- do nothing return; } workerDialog.setVisible(true); } } } // class that holds the JPanel that does background communication @SuppressWarnings("serial") class SWEx2WorkerPanel extends JPanel { private final JLabel statusLabel = new JLabel("Status: ", JLabel.CENTER); private final JTextArea textArea = new JTextArea(20, 30); private StartAction startAction = new StartAction("Start", KeyEvent.VK_S); private StopAction stopAction = new StopAction("Stop", KeyEvent.VK_T); private JProgressBar bar = new JProgressBar(); private BackgroundTask backgroundTask; private int processStatus; public SWEx2WorkerPanel() { setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); setLayout(new BorderLayout(5, 5)); textArea.setFocusable(false); JScrollPane sp = new JScrollPane(); sp.setBorder(BorderFactory.createTitledBorder("Output: ")); sp.setViewportView(textArea); stopAction.setEnabled(false); JPanel buttonPanel = new JPanel(); buttonPanel.add(new JButton(startAction)); buttonPanel.add(new JButton(stopAction)); buttonPanel.add(bar); add(statusLabel, BorderLayout.PAGE_START); add(sp, BorderLayout.CENTER); add(buttonPanel, BorderLayout.PAGE_END); } public void startProcess() { if (backgroundTask != null && !backgroundTask.isDone()) { return; // background task not yet done } textArea.setText(""); startAction.setEnabled(false); stopAction.setEnabled(true); backgroundTask = new BackgroundTask(); backgroundTask.addPropertyChangeListener(new BGTaskListener()); backgroundTask.execute(); bar.setIndeterminate(true); } public void cancelProcess() { if (backgroundTask != null && !backgroundTask.isDone()) { backgroundTask.cancel(true); } } public void processStopped() { statusLabel.setText((backgroundTask.getState()).toString() + " " + processStatus); stopAction.setEnabled(false); startAction.setEnabled(true); bar.setIndeterminate(false); // Window thisWindow = SwingUtilities.getWindowAncestor(textArea); // thisWindow.dispose(); } public int getProcessStatus() { return processStatus; } private class BGTaskListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue() == SwingWorker.StateValue.DONE) { processStopped(); } // percolate this listener up to the main JPanel's Prop Chng // Listener SWEx2WorkerPanel.this.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); } } private class BackgroundTask extends SwingWorker { @Override protected Integer doInBackground() throws Exception { List list = new ArrayList<>(); list.add("ping"); String name = System.getProperty("os.name"); if (name.startsWith("Win")) { list.add("-n"); } else { list.add("-c"); } list.add("5"); list.add("google.com"); try { ProcessBuilder pb = new ProcessBuilder(list); pb.redirectErrorStream(true); Process p = pb.start(); String s; BufferedReader stdout = new BufferedReader( new InputStreamReader(p.getInputStream())); while ((s = stdout.readLine()) != null && !isCancelled()) { publish(s); } if (!isCancelled()) { processStatus = p.waitFor(); } p.getInputStream().close(); p.getOutputStream().close(); p.getErrorStream().close(); p.destroy(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(System.err); } return processStatus; } @Override protected void process(java.util.List messages) { statusLabel.setText((this.getState()).toString()); for (String message : messages) { textArea.append(message + "\n"); } } } private class StartAction extends AbstractAction { public StartAction(String name, int mnemonic) { super(name); putValue(MNEMONIC_KEY, mnemonic); } @Override public void actionPerformed(ActionEvent e) { startProcess(); } } private class StopAction extends AbstractAction { public StopAction(String name, int mnemonic) { super(name); putValue(MNEMONIC_KEY, mnemonic); } @Override public void actionPerformed(ActionEvent e) { cancelProcess(); } } } 

编辑2

在您最新的代码迭代中:

 public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { System.out.println("Here I start"); // note that the use of invokeLater twice is not necessary SwingUtilities.invokeLater(() -> new SwingWorkerExample().displayGUI()); // there is nothing in the code that pauses or delays this line of code System.out.println("I'll show up when the SwingWorkerExample has finnished"); } }); } 

边问题:没有必要在已经排队在Swing线程上调用的代码中对Swing线程上的代码进行排队。

有问题的问题:你的println语句是在启动GUI后立即生成的 – 什么是阻止它被调用? 您需要两种机制中的一种来实现此延迟。

  1. 使用某种回调,任何种类,或
  2. 将图像处理GUI显示为模式对话框,这样它将延迟来自同一线程中的调用程序的任何代码,并在对话框可见后调用。 延迟代码将暂停,直到对话框不再存在。

第一种方式是两者中更灵活,因为它不需要使用modal dialog。

以下两个上述机制的示例。 注意代码的更改已用\\ !!表示\\ !! 评论:

 import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.Dialog.ModalityType; import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import javax.swing.*; import static javax.swing.Action.MNEMONIC_KEY; public class SwingWorkerExample2 { private JDialog modalDialog; // !! a modal JDialog private ExecuteFrame backgroundTask; private Runnable myCallback; // !! private class properyListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue() == SwingWorker.StateValue.DONE) { int processState = backgroundTask.getProcessStatus(); System.out.println("Process State: " + processState + "\n"); // !! added myCallback.run(); // simply run it. No need to place into a new thread } } } // !! set myCallback field. This could also be done as a parameter to // !! the displayGUI(Runnable myCallback) method if desired public SwingWorkerExample2(Runnable myCallback) { this.myCallback = myCallback; } private void displayGUI() { // !! create it as a modal dialog modalDialog = new JDialog(null, "Swing Worker Example", ModalityType.APPLICATION_MODAL); modalDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); // !! backgroundTask = new ExecuteFrame(); modalDialog.add(backgroundTask); backgroundTask.addPropertyChangeListener(new properyListener()); modalDialog.pack(); modalDialog.setLocationByPlatform(true); modalDialog.setVisible(true); backgroundTask.startProcess(); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { System.out.println("Here I start"); Runnable myCallback = new Runnable() { @Override public void run() { System.out.println("This is being displayed from a Runnable"); } }; // pass callback Runnable into SwingWorkerExample2's constructor new SwingWorkerExample2(myCallback).displayGUI(); // !! not wrapped in a Runnable System.out.println("This is displayed after the dialog is no longer visible"); } }); } } @SuppressWarnings("serial") class ExecuteFrame2 extends JPanel { private final JLabel statusLabel = new JLabel("Status: ", JLabel.CENTER); private final JTextArea textArea = new JTextArea(20, 30); private StartAction startAction = new StartAction("Start", KeyEvent.VK_S); private StopAction stopAction = new StopAction("Stop", KeyEvent.VK_T); private JProgressBar bar = new JProgressBar(); private BackgroundTask backgroundTask; private int processStatus; public ExecuteFrame2() { setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); setLayout(new BorderLayout(5, 5)); textArea.setFocusable(false); JScrollPane sp = new JScrollPane(); sp.setBorder(BorderFactory.createTitledBorder("Output: ")); sp.setViewportView(textArea); stopAction.setEnabled(false); JPanel buttonPanel = new JPanel(); buttonPanel.add(new JButton(startAction)); buttonPanel.add(new JButton(stopAction)); buttonPanel.add(bar); add(statusLabel, BorderLayout.PAGE_START); add(sp, BorderLayout.CENTER); add(buttonPanel, BorderLayout.PAGE_END); } public void startProcess() { if (backgroundTask != null && !backgroundTask.isDone()) { return; // background task not yet done } textArea.setText(""); startAction.setEnabled(false); stopAction.setEnabled(true); backgroundTask = new BackgroundTask(); backgroundTask.addPropertyChangeListener(new BGTaskListener()); backgroundTask.execute(); bar.setIndeterminate(true); } public void cancelProcess() { if (backgroundTask != null && !backgroundTask.isDone()) { backgroundTask.cancel(true); } } public void processStopped() { statusLabel.setText((backgroundTask.getState()).toString() + " " + processStatus); stopAction.setEnabled(false); startAction.setEnabled(true); bar.setIndeterminate(false); // Window thisWindow = SwingUtilities.getWindowAncestor(textArea); // thisWindow.dispose(); } public int getProcessStatus() { return processStatus; } public class BGTaskListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue() == SwingWorker.StateValue.DONE) { processStopped(); } // percolate this listener up to the main JPanel's Prop Chng // Listener ExecuteFrame2.this.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); } } private class BackgroundTask extends SwingWorker { @Override protected Integer doInBackground() throws Exception { List list = new ArrayList<>(); list.add("ping"); String name = System.getProperty("os.name"); if (name.startsWith("Win")) { list.add("-n"); } else { list.add("-c"); } list.add("5"); list.add("google.com"); try { ProcessBuilder pb = new ProcessBuilder(list); pb.redirectErrorStream(true); Process p = pb.start(); String s; BufferedReader stdout = new BufferedReader( new InputStreamReader(p.getInputStream())); while ((s = stdout.readLine()) != null && !isCancelled()) { publish(s); } if (!isCancelled()) { processStatus = p.waitFor(); } p.getInputStream().close(); p.getOutputStream().close(); p.getErrorStream().close(); p.destroy(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(System.err); } return processStatus; } @Override protected void process(java.util.List messages) { statusLabel.setText((this.getState()).toString()); for (String message : messages) { textArea.append(message + "\n"); } } } private class StartAction extends AbstractAction { public StartAction(String name, int mnemonic) { super(name); putValue(MNEMONIC_KEY, mnemonic); } @Override public void actionPerformed(ActionEvent e) { startProcess(); } } private class StopAction extends AbstractAction { public StopAction(String name, int mnemonic) { super(name); putValue(MNEMONIC_KEY, mnemonic); } @Override public void actionPerformed(ActionEvent e) { cancelProcess(); } } } 

您可以改用Thread。 尝试这个:

 Thread t = new Thread(new Runnable(){ @Override public void run() { //The stuff you want to finish first } }).start(); t.join(); 

这将创建一个新的线程并等待它完成。