我基于Jsoup创建了一个解析器。此解析器处理具有分页的页面。例如,该页面包含100个要解析的链接。我创建了一个超越分页的主循环。我需要运行异步任务来解析每个页面上的100个项目。据我了解,Jsoup不支持异步请求处理。处理完每个项目后,我需要将其保存到DB。我希望在插入DB表时避免错误(如果线程将同时对不同的项使用相同的id,如果可能的话)。你能建议什么? 我可以使用简单的Thread实例来解析每个项目:
public class ItemParser extends Thread {
private String url;
private MySpringDataJpaRepository repo;
public ItemParser(String url, MySpringDataJpaRepository repoReference) {
this.url = url;
this.repo = repoReference;
}
@Override
public void run() {
final MyItem item = jsoupParseItem();
repo.save(item);
}
}
运行如下:
public class Parser {
@Autowired
private MySpringDataJpaRepository repoReference; // <-- SINGLETON
public static void main(String[] args) {
int pages = 10000;
for (int i = 0; i < pages; i++) {
Document currentPage = Jsoup.parse();
List<String> links = currentPage.extractLinks(); // contains 100 links to be parsed on each for-loop iteration
links.forEach(link -> new ItemParser(link, repoReference).start());
}
}
}
我知道这段代码不可编辑,我只想告诉你我的想法。
或者也许最好使用Spring Batch? 解决这个问题的最佳做法是什么? 你觉得怎么样?
答案 0 :(得分:2)
如果使用行级锁定应该没问题。它可能会节省问题,让每个插入都是一个事务,但这会产生影响,因为事务作为一个工作单元的整个概念(即如果单个插入失败,您是否希望整个运行失败并回滚?)。
此外,如果您使用UUID或db生成的ID,则您不会遇到任何冲突问题。
至于如何构造代码,我将看看每个任务使用Runnables,以及线程池执行器。太多的线程和系统将失去效率,试图管理它们。我注意到你正在使用spring,所以看看https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html