0

我开发了一个网络爬虫。Web scraper 使用 6 个线程,每个线程打开一个网页,获取文章的文本,然后将文本的每个单词写入(使用驱动程序)到 mysql 数据库中。

在程序执行期间,我得到一个 java mysql java.lang.OutOfMemoryError: Java heap space。我在Eclipse上安装了Memory Analyzer,发现问题是由mysql驱动连接引起的:当我运行这个程序时,5分钟后驱动占用的内存是6 MB,再过5分钟200MB,再过5分钟500Mb和然后我得到java错误堆空间。

我不明白为什么会这样。

这是我用于模型的代码(访问 mysql DB)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class model {

    private Connection connect = null;

    public model(){
         try {

              Class.forName("com.mysql.jdbc.Driver");
              connect = DriverManager.getConnection("jdbc:mysql://localhost/system?user=keyword_tool&password=l0gripp0");

            } catch (Exception e) {
                System.out.println(e);
            }
    }

    public synchronized void insertCat(String parola, String categoria){

        try{
            PreparedStatement statement = connect.prepareStatement("insert into sostantivi (nome, categoria) values (?, ?)");
            statement.setString(1, parola);
            statement.setString(2, categoria);

            statement.executeUpdate();
            statement.close();

        } catch (Exception e){
            //System.out.println(e);
        }

    }

    public void closeDBConnection() {
        try {
            connect.close();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

每个线程只需调用方法 insertCat 并在数据库中插入一个带有类别的单词。

Eclipse 的 Memory Analyzer 插件说:

在此处输入图像描述

在此处输入图像描述

4

3 回答 3

2

根据您的评论,您只创建了一个“模型”(这是一个糟糕的类名)并在 6 个线程中使用它。

这不是特别好的设计——它要么通过在单个数据库连接上同步(当您可以使用每个线程一个时)限制性能,要么遇到潜在的并发问题/错误。

我只com.mysql.jdbc.JDBC4Connection在你的堆转储中看到一个。

这可能是由于误导性显示,或者(哪个理论符合您声称的“单一模型”方法)它充满了 PreparedStatements 或其他东西。

理论上,这些应该被缓存和重用——在实践中,你遇到了问题。可以尝试以下三个步骤:

  1. 更新 MySQL 驱动版本;
  2. 每 1000 条左右的语句关闭并重新打开连接;
  3. 给每个线程它自己的连接,或使用连接池。

这看起来像是 Prepared Statement 缓存的某种问题。除非您可以在代码中发现 PreparedStmt 或 ResultSet 处理的其他错误——其前景并不明显——1) 和 2) 最有可能提供解决方案/或特定的解决方法。

于 2013-08-27T09:20:53.493 回答
0

该代码永远不会关闭与数据库的连接。

尝试在方法中创建/关闭连接insertCat。应尽快获得和释放连接。连接应该只在执行持久性操作所需的时间内打开。

public class model {

    public synchronized void insertCat(String parola, String categoria){
        Connection connect = null;
        try{
            Class.forName("com.mysql.jdbc.Driver");
            connect = DriverManager.getConnection("jdbc:mysql://localhost/system?user=keyword_tool&password=l0gripp0");
            PreparedStatement statement = connect.prepareStatement("insert into sostantivi (nome, categoria) values (?, ?)");
            statement.setString(1, parola);
            statement.setString(2, categoria);

            statement.executeUpdate();
            statement.close();

        } catch (Exception e){
            //System.out.println(e);
        }finally{
           if(connect != null){
               try {
                  connect.close();
               } catch (Exception e) {
                  System.out.println(e);
               }
           }
        }

    }

}
于 2013-08-27T09:12:57.117 回答
0

如果您创建新模型而不破坏它,则会创建一个新连接,您的地图中有 2000000 个模型,因此您将有 2000000 个连接。

您应该将所有连接代码提取到连接管理器池中,并自己管理连接。

于 2013-08-27T09:17:25.307 回答