我正在尝试同时下载其网址存储在数据库中的网站的HTML代码(大约3百万条目)。
很明显我应该使用多线程技术但是我在java中如何做到这一点很麻烦。
这是我以前没有多线程的方式:
final Connection c = dbConnect(); // register jdbc-driver and establish connection
checkRequiredDbAndTables(); // here we check the existence of the Db and necessary tables
try {
// now get list of urls from the db
String sql = "select id, website_url, category_id from list_of_websites";
PreparedStatement ps = c.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
// column numeration in ResultSet is from 1 !
final long id = rs.getInt(1); // get website id
final String url = rs.getString(2); // get website url
System.out.println("Category: " + rs.getString(3) + " " + id + " " + url);
if ( isValidURL(url) && connectionOK(url) ) {
// checked url syntax and connection
String htmlInPage = downloadHTML(url);
if (!htmlInPage.equals("")) {
// add result to db
insertDataToDb( c, id, htmlInPage);
}
}
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
closeConnection(c); // database connection closed
函数donloadHTML
使用JSoup
库来完成主要工作。
感觉我的任务是一种“生产者消费者问题”。我想它可以用这样的方式表示:有一个缓冲区,包含N个链接;一些进程从它获取链接和下载HTML;和一个进程,其目的是将db中的新URL加载到缓冲区中,因为它变为空。
但我完全不知道该怎么做。我听说Threads
和ExecutorService
提供了ThreadPools
,但它对我来说真的很混乱。
答案 0 :(得分:2)
您可能想要使用Thread pool that has fixed amount of thread。您的计划将首先create a thread pool。然后它将从数据库中读取URL。读取URL后,程序将start a new task下载其内容。
您的程序可能会保留queue。当任务完成下载HTML时,它可以将URL和结果一起推送到队列中。当主线程完成读取URL和启动任务时,它可以等待队列。 Once the queue have any responses,take the response out并将其写入数据库。主线程可以计算接收到的响应数量,当计入URL数量时,所有任务都完成。
您的程序可以编写一个类来存储带有URL的响应,例如:
class response {
public String URL;
public String result;
public response(String u, String r) { this.URL = u; this.result = r; }
}
如果你仍然有任何实施或理解方面的问题(我可能不会解释清楚,现在是00:40,我很快就会入睡。),请留下评论。如果您需要代码,请同时留下评论。
答案 1 :(得分:0)
主线程:
for
每条记录:
ArrayBlockingQueue
main
下载主题:
while
不是数据结束标记: