Request to create separate thread in java?

Below is a compiled software replica of the actual problem code,

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

      

where I would like to run a block if{}

in main () on a separate thread. Since these 2 lines,

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

      

no need to wait for the if(){}

block to complete

Another problem is that experts recommend running confirmation-dialog methods in the event stream.

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

      

Please help me!!!!

+3


source to share


2 answers


JOptionPane is a Swing method and should be called in EDT, E vent D ispatch T hread, and only on this thread, and therefore it assumes that all your code above should be on EDT and that most of your calls are SwingUtilities.invokeLater(new Runnable()

completely unnecessary. The only ones needed are the main ones where you run your Swing GUI code and any areas where Swing calls must be made from background threads. Again, if any of the above code is running on background threads, then the JOptionPane should not be on that thread.

For more specific information in this or any other answer, please provide more specific information in your question. Let all confusion end. The best way to get us fully and quickly understand your problem would be if you want to create and publish a minimal example program , a small but complete program that only has the necessary code to demonstrate your problem that we can copy, paste, compile and run unchanged.

I have a suspicious suspicion that a decent refactoring along the lines of MVC can solve most of your problems. Your code is very linear, with its lines of code that need to follow each other and its if blocks, and also tightly coupled to your GUI, two red flags for me. It might be better to have less linear code, more event and state code, code where your background code interacts with the GUI via an observer notification, and where the background code also responds to state changes in the GUI from the control notification.




You need two SwingWorkers for your control, one to count the rows and the other to get the rest of the data if the user chooses to do so. I will add a PropertyChangeListener to the first SwingWorker to be notified when the row count data is ready, and then when it is present, present it for presentation so the user can choose whether to continue or not. If he decides to continue, I would call the second SwingWorker to get the bulk of the data.




For example, a rough sketch of what I'm talking about:

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

      

The key to all of this is not to think in a linear console mode, but rather to use the observer design pattern i.e. listeners of some kind to check for state change of both the GUI and the model.

Essentially:

  • create employee
  • add observer to worker (property change listener)
  • perform a worker
  • display a progress bar dialog or notify the user in some way that the worker is executing.

  • The listener will be notified of the worker's get()

    progress , and then you can query the worker (here via a method call ) for its final result.

  • Then the progress dialog can be closed
  • And the view can display the result or receive additional information from the user.
+3


source


Yes; SwingUtilities.invokeLater () just puts your runnable in the AWT event queue for later processing, and it's safe at all times.



0


source







All Articles