假设我为同一个URL实例化了多个爬虫。它们将URL写入MySQL数据库进行处理。在处理URL之前,它们会检查数据库中是否存在该页面的记录,这样就不会再次处理已经处理过的页面。
问题是,应该存在某种类型的锁,这样,如果我的逻辑是正确的,那么它们中只有一个可以从特定的表中读取或写入。因此,我只实例化了一个数据库连接(JDBC)供它们使用。尽管如此,我仍然不确定这是不是正确的做法。
所以我的问题是:从单个数据库连接执行的语句是按顺序运行的(它们是排队的)还是取决于数据库引擎的配置。
发布于 2015-05-06 16:34:47
因此,我只实例化了一个数据库连接(
)供它们使用。尽管如此,我仍然不确定这是不是正确的做法。
我最近遇到了一些类似的情况。我选择只有一个JDBC连接,并使用Lock在线程之间共享这个连接。
需要某种状态标志来指示一个特定的URL正在被处理。
查看我下面的简单代码片段,它说明了前面的几点。
从单个数据库连接执行的
do语句是按顺序运行(它们是排队的)还是取决于数据库引擎的配置。
要消除任何疑虑,请让您的Java代码确保语句按顺序运行。这将消除任何来自意外错误的后遗症。
代码片段
CrawlerThread.java
public class CrawlerThread extends Thread {
public void run() {
String url=null;
try {
String url = urlDao.getNextUrlToProcess();
if (url!=null) {
// Process URL here...
}
} catch(Exception e) {
// Handle exception here...
} finally {
urlDao.markUrlAsFetched(url);
}
}
}UrlDAO.java
public class UrlDAO {
public String getNextUrlToProcess() {
Connection jdbcConnection = null;
String url = null;
try {
jdbcConnection = connectionManager.acquireSharedConnection();
// Perform query to get next url
// SELECT url FROM urls WHERE status = 'NEED_FETCH' LIMIT 1
ResultSet rs = ...
if (rs.next()) {
url = ...
// Mark url as being processed
setUrlStatus(jdbcConnection, url, 'BEING_FETCHED');
}
} catch(Exception e) {
// Handle exception here...
} finally {
connectionManager.releaseSharedConnection();
}
return url;
}
public void markUrlAsFetched(String url) {
Connection jdbcConnection=null;
try {
jdbcConnection = connectionManager.acquireSharedConnection();
setUrlStatus(jdbcConnection, url, 'FETCHED');
} catch(Exception e) {
// Handle exception here...
} finally {
connectionManager.releaseSharedConnection();
}
}
private void setUrlStatus(Connection jdbcConnection, String url, String newStatus) {
// UPDATE urls SET status = ? WHERE url = ?
if (url!=null) {
...
}
}
}ConnectionManager.java
/**
*
* The ConnectionManager opens, closes and shares a JDBC connection among the different threads.
*
*/
public class ConnectionManager {
private Lock connectionLock = new ReentrantLock();
private Connection sharedConnection = ...
public Connection acquireSharedConnection() {
connectionLock.lock();
return sharedConnection;
}
public void releaseSharedConnection() {
connectionLock.unlock();
}
}https://stackoverflow.com/questions/30018389
复制相似问题