调用数据库时应用程序冻结 [英] Application is freezing when database is called

查看:75
本文介绍了调用数据库时应用程序冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Java的ComponentAdapter中实现了很多东西.由于它确实从数据库加载数据并显示在JTable中,因此我将其添加到了另一个线程中.我将向您展示一种被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());
             }
     }

并且,以上线程可以通过3种方式调用.即是通过ItemListener连接到JComboBoxActionListener连接到JMenuComponentListener.

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

我有很多这类方法可以从数据库中获取数据,并提供JTables并从GUI中获取数据并保存在数据库中.

现在我的问题是,每当发生数据库调用时,所有这些有时都会冻结.我以为是Thread问题的bcs,所以我做了上面的DisplayInitialRevenue_Thread来调用displayInitialRevenue_Method()作为测试.然后,我只调用了与调用此方法相关的区域,但有时仍然冻结!我的其他数据库方法不在单独的线程中,但是这是方法,因此,为什么甚至调用仅"此方法也会导致此冻结?它在线程中!

旁注,我使用Java 8,使用MySQL Server版本:5.6.16-XAMPP随附的MySQL Community Server(GPL).

解决方案

调用t.start()来启动新的Thread,调用Thread#run不会执行任何操作,然后在内部调用Threadrun方法.相同的线程上下文...

已经说过,Swing不是线程安全的,Swing要求对UI的所有更新都必须在Event Dispatching Thread的上下文内进行.代替使用Thread,您应该考虑使用SwingWorker,它可以让您在后台线程中执行长时间运行的任务,但是它提供了易于使用的publish/process方法,并在出现以下情况时调用done它会完成,在您的EDT上下文中执行.

有关更多详细信息,请参见 Worker Threads和SwingWorker >

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.

解决方案

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

这篇关于调用数据库时应用程序冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆