【问题标题】:Java MySQL query thread keeps increasing memory usageJava MySQL 查询线程不断增加内存使用量
【发布时间】:2013-03-30 12:21:00
【问题描述】:

我有一个名为 QueryTest 的方法,它通过网络查询 MySQL 数据库以获取名为 output 的表。从一开始,这个方法在运行时会不断消耗更多的内存,直到最终遇到内存不足的错误。我已经删除了我能想到的所有内容,甚至将查询放入一个有 500 毫秒超时的循环中,但仍然没有运气。

该程序旨在在内存不足的设备上运行,因此我不能让它继续增加内存使用量。

请在下面查看我的代码。这个类被另一个只包含 new Thread(new QueryTest()).start() 并没有其他作用。

编辑 1:如果我添加 System.gc ();就在 Thread.sleep 之前,它为我的程序增加了大约 7mb,但问题消失了。我知道该方法只能提示垃圾收集器,所以这是一个可靠的解决方法吗?

// Add the main package
package DBTest;


// Import List
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;


public class QueryTest implements Runnable
{
    // Constant Objects
    public static Connection connection = null;
    ResultSet rs;
    ResultSetMetaData rsmd;
    Statement s;


    // Variables
    int portA = 0;
    int size = 0;
    String outputs [][] = new String [0][5];
    boolean isRunning = true;
    boolean isPaused = false;



    // The main method for starting the thread
    public void run ()
    {       
        // Try to connect to the database and query the updates
        try
        {       
            // Load the database driver
            Class.forName("com.mysql.jdbc.Driver").newInstance();       

            // Connect to the database
            connection = DriverManager.getConnection ("jdbc:mysql://192.168.1.103/noah", "root", "0004e5dcb6a");
            System.out.println ("Connection Made");

            // let the loop run while the thread is allowed to run
            while (isRunning)
            {       
                // Query the database if the thread is not paused
                if (!isPaused)
                {
                    // Create a prepared statement
                    s = connection.createStatement ();

                    // Execute the query and store the results
                    rs =  s.executeQuery ("SELECT * FROM outputs");

                    // Get the result set meta data
                    rsmd = rs.getMetaData();

                    // Set the result set to the last row
                    rs.last();

                    // Get the last row number
                    size = rs.getRow();

                    // Set the result set to the last row
                    rs.first();

                    /*// Get port A values
                    for (int a = 0; a < 8; a ++)
                    {
                        // Check if the output is active
                        if (Integer.parseInt(outputs [a][4]) == 1)
                        {
                            // Add to the port
                            portA = portA + Integer.parseInt (outputs [a][3]);
                            System.out.println (portA);
                        }
                    }*/

                    // Set the value of portA
                    portA = 0;
                }

                // Let the thread sleep
                Thread.sleep (500);
            }   

            // Close the connection
            connection.close();
            System.out.println ("Connection Closed");   
        }

        // Catch a error
        catch (Exception queryDatabaseErr)
        {
            System.out.println (queryDatabaseErr);
        }
    }
}

【问题讨论】:

    标签: mysql multithreading memory


    【解决方案1】:

    关闭语句,并在不需要时释放结果集。在循环的 and 处。

        ...
        rs.close();  //free result set
        s.close();   //close the statement
        Thread.sleep(500)
    }
    

    我的 java 应用程序中有相同的 propbem。有时我在下面写的解决方案没有帮助。但是在我开始使用其他数据库库后:http://sourceforge.net/projects/c3p0/,内存使用量急剧下降,应用程序运行得更快。它使用持久连接,所以我建议只使用控制台或桌面应用程序,而不是 Java Servlet Pages。

    我推荐阅读这个主题:Java MySQL JDBC Memory Leak ;)

    在您安装或添加 C3P0 库到您的项目后,只需导入:

    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    

    在此之后您不必更改代码(我记得,但您应该阅读此库的手册http://www.mchange.com/projects/c3p0/apidocs/com/mchange/v2/c3p0/ComboPooledDataSource.html

    【讨论】:

    • 在尝试了这么多事情之后,我完全忘了把它放回去,但它仍然没有任何区别。仍然存在相当稳定的内存增长。
    • 这里有一些有趣的事情。如果我使用 System.gc () 提示垃圾收集器;就在我执行 sleep 之前,它增加了大约 7mb 的内存使用量,但问题消失了。问题是我知道 gc ();只能暗示垃圾收集器,所以我不知道从长远来看这会有多可靠。
    • 是的 Garbage Colelctor 可以帮助你,但从长远来看,我也没有经验。我长期使用 C3P0 库,/5-6,000,000 sql queryes/ 速度快了 10 倍,内存使用量是恒定的。另一件事是,如果您在 IDE 中调试代码,或者从命令行/控制台运行代码,则内存使用结果可能会有所不同。我总是在控制台中测试内存使用情况,因为 IDE 调试器中也可能存在错误,这会导致内存使用量增加。
    • 谢谢。尝试了上述的库,它产生了明显的不同。
    猜你喜欢
    • 1970-01-01
    • 2017-04-02
    • 2017-09-17
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    相关资源
    最近更新 更多