2014-12-23 22 views
3

下面是实际的问题代码编译的程序副本,查询在java中创建单独的线程?

import javax.swing.JOptionPane; 
import javax.swing.SwingUtilities; 

public class Dummy { 

    public static boolean getUserCheck(int size, boolean Check) { 
     if (Check) { 
      int ret = JOptionPane.showConfirmDialog(null, size + " entries, Yes or no?", 
        "Warning", 0); 
      if (ret > 0) { 
       System.out.println("User said No: " + ret); 
       return false; 
      } else if (ret <= 0) { 
       System.out.println("user said Yes: " + ret); 
       return true; 
      } 
     } 
     return true; 
    } 

    public static void workerMethod1() { 
     System.out.println("am worker method 1"); 
    } 

    public static void workerMethod2() { 
     System.out.println("am worker method 2"); 
    } 

    public static void main(String[] args) { 
     System.out.println("mainthread code line 1"); 
     int size = 13; 
     boolean thresholdBreach = true; 

     if (getUserCheck(size, thresholdBreach)) { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        workerMethod1(); 
       } 
      }); 

      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        workerMethod2(); 
       } 
      }); 
     } 
     System.out.println("mainthread code line 2"); 
     System.out.println("mainthread code line 3"); 
    } 
} 

其中我想在主上单独的线程运行if{}块()。由于这两条线,

 System.out.println("mainthread code line 2"); 
     System.out.println("mainthread code line 3"); 

不需要等待if(){}

的另一个问题是完成后,专家建议上运行事件线程确认,对话的方法。

int ret = JOptionPane.showConfirmDialog(null, size + " entries, Yes or no?", 
        "Warning", 0); 

请帮我!!!!

+2

是的,你可以,但你为什么要? –

+2

这可能是一个XY问题类型的问题,但不管它是否是,问题都可以从更多的上下文中受益。你为什么要考虑这样做?你想达到什么样的总体目标? –

+1

为什么你认为你不能将它嵌入到任意深度?测试任何代码时,您会考虑同样的观点。涵盖测试软件的所有要点是一个太广泛的问题。 –

回答

0

是; SwingUtilities.invokeLater()只是简单地将您的可运行列表放在AWT事件队列中,以便以后处理,并且随时都可以这样做。

3

的JOptionPane是Swing的方法,并应在美国东部时间被调用,ê发泄d ispatch 牛逼 hread,只有在此线程,因此它表明,所有代码上面应该是在美国东部时间,并且你的大多数SwingUtilities.invokeLater(new Runnable()电话是完全没有必要的。唯一必需的将是主要的,您可以在其中启动Swing GUI代码,以及Swing调用需要在后台线程中创建的任何区域。同样,如果上面的代码是在后台线程中创建的,那么JOptionPane不应该在该线程中。

有关本文或其他答案的更多具体信息,请在您的问题中提供更具体的信息。让我们结束一切困惑。如果您想要创建并发布minimal example program,这是一个小而完整的程序,只有必要的代码来演示您的问题,我们可以复制,粘贴,编译和没有修改就运行。

我有一个偷偷摸摸的怀疑,一个体面的MVC线重构可以解决你的大部分问题。你的代码是非常线性的,它的代码行必须跟随另一个和它的if块,它也与你的GUI紧密耦合,对我来说是两个红旗。也许更好的办法是减少线性代码,更多的事件和状态驱动代码,后台代码通过观察者通知与GUI进行交互的代码,以及后台代码同样响应GUI中来自控制通知的状态更改的位置。


你的控制需要两个SwingWorkers,一个让行计数和其他获取数据的其余部分,如果用户决定这样做。我将向第一个SwingWorker添加一个PropertyChangeListener,以在行计数数据准备就绪时收到通知,然后一旦将其呈现给用户选择是否继续的视图。如果他决定继续,我会打电话给第二个SwingWorker来获取数据的主体。


例如,什么我谈论的草图:

import java.awt.Dialog.ModalityType; 
import java.awt.Dimension; 
import java.awt.Window; 
import java.awt.event.ActionEvent; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Random; 
import java.util.concurrent.ExecutionException; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class SwingWorkerFooView extends JPanel { 
    private static final int PREF_W = 400; 
    private static final int PREF_H = 300; 
    private JProgressBar progressBar; 
    private JDialog dialog; 

    public SwingWorkerFooView() { 
     add(new JButton(new ButtonAction("Foo", this))); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
     return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    public boolean showOptionGetAllData(int numberOfRows) { 
     String message = "Number of rows = " + numberOfRows + ". Get all of the data?"; 
     String title = "Get All Of Data?"; 
     int optionType = JOptionPane.YES_NO_OPTION; 
     int result = JOptionPane.showConfirmDialog(this, message, title, optionType); 

     return result == JOptionPane.YES_OPTION; 
    } 

    public void showProgressBarDialog() { 
     progressBar = new JProgressBar(); 
     progressBar.setIndeterminate(true); 
     Window window = SwingUtilities.getWindowAncestor(this); 
     dialog = new JDialog(window, "Hang on", ModalityType.APPLICATION_MODAL); 
     JPanel panel = new JPanel(); 
     panel.add(progressBar); 
     dialog.add(panel); 
     dialog.pack(); 
     dialog.setLocationRelativeTo(this); 
     dialog.setVisible(true); 
    } 

    public void closeProgressBarDialog() { 
     dialog.dispose(); 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("SwingWorkerFoo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new SwingWorkerFooView()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

@SuppressWarnings("serial") 
class ButtonAction extends AbstractAction { 
    Workers workers = new Workers(); 
    private SwingWorker<Integer, Void> firstWorker; 
    private SwingWorker<List<String>, Void> secondWorker; 
    private SwingWorkerFooView mainGui; 

    public ButtonAction(String name, SwingWorkerFooView mainGui) { 
     super(name); 
     this.mainGui = mainGui; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     firstWorker = workers.createFirstWorker(); 
     firstWorker.addPropertyChangeListener(new FirstPropertyChangeListener()); 
     firstWorker.execute(); 
     mainGui.showProgressBarDialog(); 
    } 

    private class FirstPropertyChangeListener implements PropertyChangeListener { 

     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
     if (evt.getNewValue() == SwingWorker.StateValue.DONE) { 
      mainGui.closeProgressBarDialog(); 
      try { 
       int numberOfRows = firstWorker.get(); 
       boolean getAllData = mainGui.showOptionGetAllData(numberOfRows); 
       if (getAllData) { 
        secondWorker = workers.createSecondWorker(); 
        secondWorker.addPropertyChangeListener(new SecondPropertyChangeListener()); 
        secondWorker.execute(); 
        mainGui.showProgressBarDialog(); 
       } else { 
        // user decided not to get all data 
        workers.cleanUp(); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } catch (ExecutionException e) { 
       e.printStackTrace(); 
      } 
     } 
     } 
    } 

    private class SecondPropertyChangeListener implements PropertyChangeListener { 
     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
     if (evt.getNewValue() == SwingWorker.StateValue.DONE) { 
      mainGui.closeProgressBarDialog(); 
      try { 
       List<String> finalData = secondWorker.get(); 

       // display finalData in the GUI 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } catch (ExecutionException e) { 
       e.printStackTrace(); 
      } 
     } 

     } 
    } 

} 

class Workers { 
    // database object that may be shared by two SwingWorkers 
    private Object someDataBaseVariable; 
    private Random random = new Random(); // just for simulation purposes 

    private class FirstWorker extends SwingWorker<Integer, Void> { 
     @Override 
     protected Integer doInBackground() throws Exception { 

     // The Thread.sleep(...) is not going to be in final production code 
     // it's just to simulate a long running task 
     Thread.sleep(4000); 

     // here we create our database object and check how many rows there are 
     int rows = random.nextInt(10 + 10); // this is just for demonstration purposes only 

     // here we create any objects that must be shared by both SwingWorkers 
     // and they will be saved in a field of Workers 
     someDataBaseVariable = "Fubar"; 

     return rows; 
     } 
    } 

    private class SecondWorker extends SwingWorker<List<String>, Void> { 
     @Override 
     protected List<String> doInBackground() throws Exception { 

     // The Thread.sleep(...) is not going to be in final production code 
     // it's just to simulate a long running task 
     Thread.sleep(4000); 

     List<String> myList = new ArrayList<>(); 
     // here we go through the database filling the myList collection 

     return myList; 
     } 
    } 

    public SwingWorker<Integer, Void> createFirstWorker() { 
     return new FirstWorker(); 
    } 

    public void cleanUp() { 
     // TODO clean up any resources and database stuff that will not be used. 
    } 

    public SwingWorker<List<String>, Void> createSecondWorker() { 
     return new SecondWorker(); 
    } 
} 

所有这一切的关键是不要想以线性控制台程序的方式,而是使用观察者设计模式,即某种类型的监听器来检查GUI和模型的状态变化。

它本质上是:

  • 创建工人
  • 增加观察员工人(属性更改侦听)
  • 执行工人
  • 显示进度条对话框或以某种方式通知用户该名工人正在执行。

  • 工作完成后会通知侦听器,然后您可以查询工作人员(此处通过方法调用get()),了解其最终结果。

  • 然后可以关闭进度对话框
  • 而且该视图可以显示结果或从用户获得附加信息。
+0

我想我已经添加了更多的信息查询,请看看 – overexchange

+0

这是[compiledprogram](https://github.com/shamhub/CS61B_Fall2006/blob/master/JavaCode/src/dummy.java),其中我想要在单独的线程上运行'if {}'块,因为主线程中的主线程代码行2和主线程代码行3不需要等待'if {}'块。这个代码的另一个问题是,我没有在事件线程上启动对话框,如上所述:“所有对话框应该在事件线程上运行” – overexchange

+0

@proxchange:参见可运行示例代码。 –

相关问题