jatula 2009-01-11 23:07
浏览 241
已采纳

数据转移OOM的问题(急)

[b]
---------Consumer myList.size():3
Consumer: 2
---------Consumer myList.size():2
Consumer: 1
---------Consumer myList.size():1
Consumer: 0
myList warning: it's empty!
star:234000
end:236000
Exception in thread "Thread-3" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2882)
at java.lang.StringCoding.trim(StringCoding.java:71)
at java.lang.StringCoding.access$100(StringCoding.java:34)
at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:147)
at java.lang.StringCoding.decode(StringCoding.java:169)
at java.lang.String.(String.java:444)
at com.mysql.jdbc.ResultSetRow.getString(ResultSetRow.java:760)
at com.mysql.jdbc.BufferRow.getString(BufferRow.java:538)
at com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5557)
at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5434)
at com.mysql.jdbc.ResultSetImpl.getStringForClob(ResultSetImpl.java:5485)
at com.mysql.jdbc.ResultSetImpl.getObject(ResultSetImpl.java:4821)
at cn.lake.databases.MysqlClass.executeQuery(MysqlClass.java:464)
at cn.lake.start.DoStart$Producer.run(DoStart.java:97)[/b]

原码部分:
package cn.lake.start;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import cn.lake.cache.DataProperties;
import cn.lake.cache.Property;
import cn.lake.databases.MysqlClass;
import cn.lake.databases.MysqlConnetionPool;
import cn.lake.util.MSTMConfig;

public class DoStart {
private LinkedList myList = new LinkedList();
private static LinkedList propertyList = new LinkedList();
private int MAX = 100;
private final Lock lock = new ReentrantLock();
private final Condition full = lock.newCondition();
private final Condition empty = lock.newCondition();

public DoStart() {
}

public void start() {
    new Producer().start();
    new Consumer().start();
}

public static void main(String[] args) throws Exception {
    DoStart s2 = new DoStart();
    addPaginateion();
    s2.start();
}

private static void addPaginateion() {
    MSTMConfig mconfig = new MSTMConfig();
    MysqlClass mysqlConnect;
    MysqlConnetionPool mysqlConnectionPool = new MysqlConnetionPool(mconfig.myServerName, mconfig.myDbName, mconfig.myLoginName,mconfig.myLoginPwd);
        List rs = null;
        String sql = "SELECT COUNT(*) as exp From tb_paid_resume_info";
        mysqlConnect = new MysqlClass(mysqlConnectionPool);
        rs = mysqlConnect.executeQuery(sql);
        int count = Integer.parseInt(((Map) rs.get(0)).get("exp")
                .toString());

        // 分页数
        int pagination = 0;
        int paginationSpare = count % mconfig.myReadCount;
        System.out.println("数据库总数据量为:" + count);
        System.out.println("分页大小为:" + mconfig.myReadCount);
        if (paginationSpare == 0) {
            pagination = count / mconfig.myReadCount;
        } else {
            pagination = count / mconfig.myReadCount + 1;
        }
        Property property = null;
        DataProperties dproperty = null;
        for (int i = 1; i <= pagination; i++) {
            int endPoint = i * mconfig.myReadCount;
            if (i == 1) {
                property = new Property(0, endPoint);
            } else {
                if (i == pagination) {
                    property = new Property((i - 1)* mconfig.myReadCount, count);
                } else {
                    property = new Property((i - 1)* mconfig.myReadCount, endPoint);
                }
            }
            propertyList.add(property);
        }
}
class Producer extends Thread {
    public void run() {
        while (true) {
            lock.lock();
            try {
                System.out.println("-------------Producer myList.size():"+myList.size());
                while (myList.size() > MAX) {
                    System.out.println("warning: it's full!");
                    full.await();
                }
                if(propertyList.size()>0){
                    List resumeRs= null;
                    MSTMConfig mconfig = new MSTMConfig();
                    MysqlClass mysqlConnect;
                    MysqlConnetionPool mysqlConnectionPool = new MysqlConnetionPool(mconfig.myServerName, mconfig.myDbName, mconfig.myLoginName,mconfig.myLoginPwd);
                    int star= propertyList.getLast().getStart();
                    int end= propertyList.getLast().getEnd();
                    System.out.println("star:"+star);
                    System.out.println("end:"+end);
                    String resumeSql = "SELECT * From tb_paid_resume_info limit "+star+","+end;
                    mysqlConnect = new MysqlClass(mysqlConnectionPool);
                    resumeRs = mysqlConnect.executeQuery(resumeSql);
                    for(int r=0;r<resumeRs.size();r++){
                        if (myList.add(r)) {
                            System.out.println("Producer: " + r);
                        }
                    }
                    empty.signal();
                    propertyList.removeLast();
                    System.out.println("==================propertyList.size():"+propertyList.size());
                }
            } catch (InterruptedException ie) {
                System.out.println("producer is interrupted!");
            } finally {
                lock.unlock();
            }

        }
    }

}
class Consumer extends Thread {
public void run() {
while (true) {
lock.lock();
try {
while (myList.size() ==0) {
System.out.println("myList warning: it's empty!");
empty.await();
}
System.out.println("---------Consumer myList.size():"+myList.size());
Object o = myList.removeLast();
System.out.println("Consumer: " + o);
full.signal();
} catch (InterruptedException ie) {
System.out.println("consumer is interrupted!");
} finally {
lock.unlock();
}
}
}
}

}

===数据库总数据量为:321323
分页大小为:2000
请各位帮看看是什么问题,老OOM,请到10万时就OOM

/**
 * 执行查询语句
 * 
 * @param sql
 * @return
 */
public List executeQuery(String sql) {
    ConnectionWrapper connectionWrapper = this.getConnectionWrapper();
    Statement stmt = this.getStmt(connectionWrapper.connection);
    List<Map> list = new ArrayList<Map>();
    int mysqlErrorTimes = 1;
    while (mysqlErrorTimes > 0 && mysqlErrorTimes <= 10) {
        try {
            ResultSet rs = null;
            rs = (ResultSet) stmt.executeQuery(sql);
            if (rs != null) {
                ResultSetMetaData rsmd = (ResultSetMetaData) rs
                        .getMetaData();
                while (rs.next()) {
                    Map<Object, Object> map = new HashMap<Object, Object>();
                    for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                        map.put(rsmd.getColumnName(i), rs.getObject(i));
                    }

                    list.add(map);
                }
            }
            rs.close();
            rs = null;
            mysqlErrorTimes = 0;
        } catch (Exception e) {
            connectionWrapper = isError(connectionWrapper, stmt, sql, e);
            stmt = this.getStmt(connectionWrapper.connection);
            mysqlErrorTimes++;
        }
    }
    this.release(connectionWrapper.connection, stmt);
    return list;
}

}
[b]问题补充:[/b]
首先,謝謝大家支持;
就是使用-Xmx参数配置你JVM执行程序时的最大使用内存。

二、如果执行以上命令仍内存溢出的话,仔细检查你的批量处理代码,修正其中的问题。

對JVM增大內存我試過,當內存增大到1G時,可以跑到10萬的量,然后又OOM,而批量處理,不好意思,這里我還沒有做批量的處理,只是打印出來而已,并沒有做插入動作,所以這個不需要考慮;

數據庫,我每次查詢都有一個
mysqlErrorTimes++;
}
}
[b]this.release(connectionWrapper.connection, stmt); [/b]
return list;
}
釋放和關閉動作,所以我才奇怪!

  • 写回答

3条回答 默认 最新

  • iteye_235 2009-01-15 11:55
    关注

    你注意在你Producer类run方法中的这一段代码:
    [code="java"]MSTMConfig mconfig = new MSTMConfig();
    MysqlClass mysqlConnect;
    MysqlConnetionPool mysqlConnectionPool = new MysqlConnetionPool(mconfig.myServerName, mconfig.myDbName, mconfig.myLoginName,mconfig.myLoginPwd);[/code]

    这段代码怎么能放在线程方法的循环体内呢?
    难道每次循环要重置池对象;你的Connection执行sql条数有限制没,如果没有限制,分页只一个Connection就足够了,你每次循环一个新获取一个新的Connection是出于什么考虑,还有你的进程中断在那里?你参照我的意见修改试试:

    一、修改你Thread子类中run方法循环体的内容,将[code="java"]MSTMConfig mconfig = new MSTMConfig();
    MysqlClass mysqlConnect;
    MysqlConnetionPool mysqlConnectionPool = new MysqlConnetionPool(mconfig.myServerName, mconfig.myDbName, mconfig.myLoginName,mconfig.myLoginPwd);[/code]移到循环体外;
    二、优化你的Connection的获取和释放,最常见的是使用try catch执行一定数目的sql后才在finally块中释放后再获取新的Connnection。
    三、仔细检查你的JDBC用法,使用SQL占位符,也是把循环体内的对象建立放置到循环体外。
    四、尽可能把你的Thread去掉,或者处理好进程中断和正确的释放资源。
    五、使用JConsole监控你的程序,看看问题再那里;

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值