需求如下,求高效的解决思路

michaelzhouh 2016-06-15 04:02:33
一次计划任务大概涉及到5W条数据需要遍历,更新其中的一个字段;
遍历的每一条数据,需要4条查询语句和1条修改语句;

java多线程以及数据访问处理,怎么样最高效?

我现在是用的java后台程序,没用线程池,直接主线程定时运行,判断到有需要处理的数据,就开启20个子线程,每个线程取出2000条数据,做业务处理,做完2000条,又到数据库取……直到5W条都计算完成。

我没用其他额外的框架,自己写的一个sqlhelper,然后所有dao类都调用它来访问数据,业务都实现了,也能计算了,现在遇到的问题是,跑到4W条左右就开始卡了,java占用cpu和内存越来越高就卡死了(我全部的查询都是返回ResultSet,在dao里面的数据访问再rs.close()的)。不知道怎么优化,如果能不用第三方扩展,直接用原生态java解决固然是最好的。sqlhelper的部分代码如下:


import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.log4j.Logger;

public final class DbHelper {
private static Connection conn = null;

private static String driver = "";
private static String url = "";
private static String userName = "";
private static String password = "";

private static Properties pp = null;
private static FileInputStream fis = null;

private static Logger logger = Logger.getLogger(DbHelper.class);

// 加载驱动,只需要一次
static {
try {
// 从配置文件dbinfo.properties中读取配置信息
pp = new Properties();
fis = new FileInputStream("system.properties");
pp.load(fis);

driver = pp.getProperty("driver");
url = pp.getProperty("url");
userName = pp.getProperty("userName");
password = pp.getProperty("password");

Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
fis = null;

}
}

private DbHelper() {}

// 此方法为获取数据库连接
public static Connection getConnection() {
try {
if (conn == null || conn.isClosed()) {
conn = DriverManager.getConnection(url, userName, password);
}
} catch (SQLException ex) {
logger.error(Common.getTrace(ex));
ex.printStackTrace();
}
return conn;
}

/**
* 增删改【Add、Del、Update】
*
* @param sql
* @return int
*/
public static int executeNonQuery(String sql) {
int result = 0;
Connection conn = null;
Statement stmt = null;

try {
conn = getConnection();
stmt = conn.createStatement();
result = stmt.executeUpdate(sql);
} catch (SQLException ex) {
ex.printStackTrace();
logger.error(Common.getTrace(ex) + " : " + sql);
close(null, stmt, conn);
}
return result;
}

/**
* 插入返回主键
*
* @param sql
* @param obj
* @return int
*/
public static int executeInsert(String sql, Object... obj) {
int result = 0;
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getConnection();
ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
for (int i = 0; i < obj.length; i++) {
ps.setObject(i + 1, obj[i]);
}

result = ps.executeUpdate();
if (result == 1) {//插入成功
rs = ps.getGeneratedKeys();
if (rs.next()) {
result = rs.getInt(1);
}
}
} catch (SQLException ex) {
ex.printStackTrace();
logger.error(Common.getTrace(ex) + " : " + sql);
close(null, ps, conn);
} finally {
close(ps);
}
return result;
}
……



public TrackingNumberModel getTrackingNumber(String tracking_number) throws Exception {
TrackingNumberModel model = new TrackingNumberModel();
String sql = "SELECT * FROM tracking_number WHERE tracking_number=? LIMIT 1";
ResultSet rs = DbHelper.executeQuery(sql, tracking_number);
while (rs.next()) {
model.setCustomerId(rs.getInt("customer_id"));
model.setAdminId(rs.getInt("admin_id"));
model.setAccountStatus(rs.getInt("account_status"));
//……
}
DbHelper.close(rs);
return model;
}

然后所有Dao里面的都没有关闭连接,程序中也没有用关闭连接(我只要加了关闭连接就要出错)。

本人能力有限,捣鼓了很久了,确实不知道怎么优化,求教大神了。哪怕给一个思路,我去研究都行。
...全文
2534 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
michaelzhouh 2017-09-27
  • 打赏
  • 举报
回复
我把哪些业务逻辑需要的大量的数据库查询操作封装成了存储过程,就OK了,现在不得卡死了。
yahle 2016-06-16
  • 打赏
  • 举报
回复
你说的慢是多慢,还有,一般db的插入效率不会太高的,看服务器的配置,也就是1k~1w/sec之间

2,408

社区成员

发帖
与我相关
我的任务
社区描述
高性能计算
社区管理员
  • 高性能计算社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧