0

I have lot of things implemented in ComponentAdapter of Java. Since it does loading data from database and displaying in JTable, I added it into another thread. I will show you one method which is being called by such ComponentAdapter

private class DisplayInitialRevenue_Thread implements Runnable
     {

        @Override
        public void run() 
        {
            displayInitialRevenue_Method();
        }

     }

     private void displayInitialRevenue_Method()
     {
        //Get the dates from the combo
        String selectedCouple = revenueYearCombo.getSelectedItem().toString();

        if(selectedCouple.equals("Select Year"))
        {
            return;
        }

        String[] split = selectedCouple.split("/");


         //Related to DB
         double totalamountInvested;



             //Get data from the database
             dbConnector = new DBHandler();
             dbConnector.makeConnection();

             DefaultTableModel model = (DefaultTableModel) initialRevenueTable.getModel();
             model.setRowCount(0);



             ResultSet selectAllDetails = dbConnector.selectAllDetails("SQL CODE HERE ");

             try
             {
                 if(selectAllDetails.isBeforeFirst()==false)
                 {
                     JOptionPane.showMessageDialog(null,"This table is empty");
                 }
                 else
                 {
                     while(selectAllDetails.next())
                     {
                         String clientName = selectAllDetails.getString("Client Name");
                         String providerName = selectAllDetails.getString("Provider Name");
                         Double amountInvested = selectAllDetails.getDouble("Invest_Amount");


                        //Get Other Data


                         //Update the table
                         Object[]row = {dateS,clientName,providerName,amountInvested};

                         model.addRow(row);

                         //Get the total
                         amountInvested = amountInvested+amountInvested;

                     }

                     //Add the sum
                     Object[]blankRow = {null,null,null,null};
                     model.addRow(blankRow);

                      Object[]row = {dateS,clientName,providerName,amountInvested};
                 }
             }
             catch(SQLException sql)
             {
                 JOptionPane.showMessageDialog(null,sql.getLocalizedMessage());
             }
     }

And, this above thread can be called in 3 ways. That is by ItemListener attached to a JComboBox, ActionListener attached to a JMenuand ComponentListener.

ComponentListener

private class DisplayInitialRevenue extends ComponentAdapter
     {
         public void componentShown(ComponentEvent e) 
         {
             formMemorizer = FormMemorizer.Initial_Revenue;
             //displayInitialRevenue_Method();

             DisplayInitialRevenue_Thread t = new DisplayInitialRevenue_Thread();
             t.run();
         }


     }

ItemListener

private class RevenueYearComboAction implements ItemListener
     {

        @Override
        public void itemStateChanged(ItemEvent e) 
        {
            if(e.getStateChange() == ItemEvent.SELECTED)
            {
                int selection = formMemorizer;

                if(selection==-1)
                {
                    return;
                }
                else if(selection==FormMemorizer.Initial_Revenue)
                {
                    //displayInitialRevenue_Method();
                    DisplayInitialRevenue_Thread t = new DisplayInitialRevenue_Thread();
                    t.run();
                }
        }
}

I have lot of these kind of methods to get the data from the database and feed the JTables and take data from GUI and save in database.

Now my question is, all of these are freezing sometimes, whenever a database call occurred. I thought it is bcs of Thread issue so I made the above DisplayInitialRevenue_Thread to call displayInitialRevenue_Method() as a test. Then I only invoked the area related to the call this method but it still freezes sometimes! My other database methods are not in separate threads, but this is method is, so why even calling "only" this method lead this to freeze? It is in a thread!

For side note, I am in Java 8, using MySQL Server version: 5.6.16 - MySQL Community Server (GPL) which comes with XAMPP.

halfer
  • 19,824
  • 17
  • 99
  • 186
PeakGen
  • 21,894
  • 86
  • 261
  • 463
  • please where it freeze, is there some JProfiler used, how, whats output from, but description talking about blocking an EDT, :-) Oracle tutorial - Event Dispatch Thread, my suggestion don't to use SwingWorker for production code, – mKorbel Nov 27 '14 at 06:28
  • voting to close as too broad – mKorbel Nov 27 '14 at 06:29
  • @mKorbel:In one of below answer says `Use SwingWorker` – PeakGen Nov 27 '14 at 06:30
  • @mKorbel: There is no place I can point, the freeze happen only "sometimes", and it happens "whatever time" the DB is called. Which means, there are lot of forms to edit,update,view records from DB, using any such form can lead this to freeze "sometimes". – PeakGen Nov 27 '14 at 06:32
  • @mKorbel `t.run();` ... – MadProgrammer Nov 27 '14 at 06:33

1 Answers1

2

Call t.start() to start a new Thread, calling Thread#run does nothing more then calls the run method of the Thread within the same thread context...

Having said that, Swing is not thread safe, Swing requires that all updates to the UI are made from within the context of the Event Dispatching Thread. Instead of using a Thread, you should consider using a SwingWorker, which allows you to execute long running tasks in a background thread, but which provides easy to use publish/process methods and calls done when it completes, which are executed within the context of the EDT for you.

See Worker Threads and SwingWorker for more details

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • *"Please give me more advice"* - Don't do what you're doing, use a `SwingWorker`. You might like to have a read through [Code Conventions for the Java TM Programming Language](http://www.oracle.com/technetwork/java/codeconvtoc-136057.html), it will make it easier for people to read your code and for you to read others – MadProgrammer Nov 27 '14 at 06:28
  • :-) don't to use SwingWorker for JDBC, is designated for enjoy – mKorbel Nov 27 '14 at 06:29
  • @mKorbel Why...? With some tweaking (additional notification), I've found it actually rather useful ;) - Add a `ExecutorService` and it reduces the pain threshold considerably... – MadProgrammer Nov 27 '14 at 06:31
  • @MadProgrammer: Imagine I am moving with `t.start()`. Some people are telling "don't update GUI using another Thread" ?? – PeakGen Nov 27 '14 at 06:37
  • @sniper All updates to the UI will need to be synchronised to execute with the context of the EDT, if you don't want to use `SwingWorker`, you will need to use `SwingUtilities.invokeLater` instead, which will highlight why I recommend `SwingWorker` – MadProgrammer Nov 27 '14 at 06:40
  • @MadProgrammer ExecutorService & SwingWorker is one of uncachable, unmanagable bug, there isn't notifications, tracing from Future (one of black tunnels in Java), nor from SwingWorker, combination of ExecutorService & SwingWorker is about why my done() sometimes isn't called (overloading number of instances, or older instance ended faster than newer) – mKorbel Nov 27 '14 at 06:41
  • yes Runnable#Thread and invokeLater(just for methods implemented in Swing APIs, to notify GUI not whole process) is way to go – mKorbel Nov 27 '14 at 06:42
  • @mKorbel I've recently falling back on using the `PropertyChangeListener` support to provide (extended/customised) notifications (start/done) as well as a custom notification to the `publish` method to make it simpler to use...better then littering the code with `SwingUtilities.invokeLater` or using reflection (and, yes, I've done this). Sounds more like an issue with `ExecutorService`, never had a situation where `done` wasn't called, have seen issue where `get` wasn't and errors when unhandled, but that's a developer issue. All thread code adds complexity and breaks traceability... – MadProgrammer Nov 27 '14 at 06:45
  • @mKorbel And how unreadable `SwingUtilities.invokeLater` makes code, even tracing that is a pain :P – MadProgrammer Nov 27 '14 at 06:47
  • @MadProgrammer this forum loves SwingWorker, but my view is there isn't any reason for, I know that this is pure flamewar, and looks like as I'm the only one that (periodically) against usage of this unmanagable, shadowing API, – mKorbel Nov 27 '14 at 06:59
  • SwingUtilities.invokeLater notify EDT, always if you want or not, if is there (and you know something about) some bug(s) then there isn't reason to use AWT/Swing for painting an GUI on the screen no longer – mKorbel Nov 27 '14 at 07:03
  • @MadProgrammer: Thanks a lot for the help. Marking this as the selected answer. – PeakGen Nov 27 '14 at 07:39
  • @mKorbel It's taken me a LONG time to figure out really how to use it, it's simpler to explain the `SwingUtilities.invokeLater` and getting information from one thread context to another it an easy and manageable fashion, but that's just my experience. I'd be interested to see actual case of where this fails – MadProgrammer Nov 27 '14 at 08:06
  • @MadProgrammer [I had playing with Executor & Runnable & SwingWorker, with real idiotic typo demonstrated in description and code](http://stackoverflow.com/q/7053865/714968) (to test VMs on VMWare) on short periods (a few steps, separate threads, if is alive, how, where, who's, how many), sometimes I'm lost part of without seeing a connection on virtual machine (reading data from embeded db, then after db invoked a new test on local machine:-) too, JVM memory increased, never profiled, ran on separate lan, – mKorbel Nov 27 '14 at 08:31