java - 并发插入数据库

标签 java jsoup spring-batch java.util.concurrent

我做了一个基于Jsoup的解析器。该解析器处理带有分页的页面。例如,该页面包含 100 个要解析的链接。我创建了一个主循环来进行分页。我需要运行异步任务来解析每个页面上的 100 个项目。据我了解,Jsoup 不支持异步请求处理。处理完每个项目后,我需要将其保存到数据库中。我想避免在插入数据库表期间出现错误(如果可能的话,线程将同时对不同项目使用相同的 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 更好? 解决这个问题的最佳实践是什么? 你觉得怎么样?

最佳答案

如果使用行级锁定应该没问题。让每个插入都是一个事务可能会解决问题,但是考虑到事务作为一个工作单元的整个概念,这会产生影响(即,如果单个插入失败,您是否希望整个运行失败并回滚?)。

此外,如果您使用 UUID 或数据库生成的 id,则不会出现任何冲突问题。

至于如何构建代码,我会考虑为每个任务使用 Runnables 以及线程池执行器。线程太多,系统会因尝试管理所有线程而失去效率。我注意到你正在使用 spring,所以看看 https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

关于java - 并发插入数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44002334/

相关文章:

c# - 为什么许多开发人员反对在 OOP 中使用 "protected"修饰符?

java - Java/Python 中的自动文本反馈分析

java - Spring Batch Json 自定义 ItemWriter

sql-server - Spring 批处理 : efficient way to query results of a stored procedure within a tasklet

java - 在 JavaFX 中显示禁用控件的工具提示

java - AbstractAction 作为 WindowListener

java - Jsoup 从表内表获取数据

java - 使用 Jsoup 从表格和网站的所有选项卡获取链接

jsoup - 如何使用jsoup限制下载大小?

java - 在网络主机上托管批处理作业与本地计算机上托管批处理作业