作者热门文章
- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在构建一个网络爬虫,我正在寻找处理我的请求以及我的线程和数据库 (MySql) 之间的连接的最佳方式。
我有两种类型的线程:
- Fetchers : They crawl websites. They produce url and add they into 2 tables : table_url and table_file. They select from table_url to continue the crawl. And update table_url to set visited=1 when they have read a url. Or visited=-1 when they are reading it. They can delete row.
- Downloaders : They download files. They select from table_file. They update table_file to change the Downloaded column. They never insert anything.
现在我正在处理这个:我有一个基于 c3p0 的连接池.每个目标(网站)都有这些变量:
private Connection connection_downloader;
private Connection connection_fetcher;
当我实例化一个网站时,我只创建了一次连接。然后每个线程都会根据它们的目标使用这些连接。
每个线程都有那些变量:
private Statement statement;
private ResultSet resultSet;
在每个查询之前我打开一个 SqlStatement :
public static Statement openSqlStatement(Connection connection){
try {
return connection.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
在每次查询之后,我关闭 sql 语句和结果集:
public static void closeSqlStatement(ResultSet resultSet, Statement statement){
if (resultSet != null) try { resultSet.close(); } catch (SQLException e) {e.printStackTrace();}
if (statement != null) try { statement.close(); } catch (SQLException e) {e.printStackTrace();}
}
现在我的 Select 查询只适用于一个选择(我现在不需要选择多个,但很快就会改变)并且定义如下:
public static String sqlSelect(String Query, Connection connection, Statement statement, ResultSet resultSet){
String result = null;
try {
resultSet = statement.executeQuery(Query);
resultSet.next();
result = resultSet.toString();
} catch (SQLException e) {
e.printStackTrace();
}
closeSqlStatement(resultSet, statement);
return result;
}
插入、删除和更新查询使用此函数:
public static int sqlExec(String Query, Connection connection, Statement statement){
int ResultSet = -1;
try {
ResultSet = statement.executeUpdate(Query);
} catch (SQLException e) {
e.printStackTrace();
}
closeSqlStatement(resultSet, statement);
return ResultSet;
}
我的问题很简单:这可以改进得更快吗?而且我担心相互排斥,以防止一个线程在另一个线程更新链接时进行更新。
最佳答案
我认为您的设计存在缺陷。为一个网站分配一个专职连接将严重限制您的整体工作量。
因为您已经设置了一个连接池,所以完全可以在使用前获取(并在之后返回)。
同样,try-with-catch
用于关闭您所有的 ResultSet
和 Statement
将使代码更具可读性 - 使用 PreparedStatement
而不是 Statement
也不会造成伤害。
一个示例(使用静态 dataSource() 调用来访问您的池):
public static String sqlSelect(String id) throws SQLException {
try(Connection con = dataSource().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT row FROM table WHERE key = ?")) {
ps.setString(1, id);
try(ResultSet resultSet = ps.executeQuery()) {
if(rs.next()) {
return rs.getString(1);
} else {
throw new SQLException("Nothing found");
}
}
} catch (SQLException e) {
e.printStackTrace();
throw e;
}
}
按照相同的模式,我建议您也为您的应用程序使用的所有不同的插入/更新/选择创建方法 - 所有这些都仅在数据库逻辑内部短时间内使用连接。
关于java - JDBC 优化多线程上的 MySql 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34743721/
我是一名优秀的程序员,十分优秀!