java - Spring 的多线程

标签 java multithreading spring threadpool threadpoolexecutor

我正在尝试进入 spring 多线程,我有几个问题。

我在 ThreadRating 类中有可运行的方法。现在我不确定使用它的最佳方式。

我找到的选项 1:

private void updateRating() {
        ExecutorService executor = Executors.newFixedThreadPool(10);

    for (int i = 0; i < 10; i++) { // test
        // thread part
        Runnable worker = new ThreadRating(path, i, products.get(i), dao, fileHandler);
        executor.execute(worker);
    }
    executor.shutdown();
    try {
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    } catch (InterruptedException e) {
        log.error("There was an error when ending threads");
        System.exit(1);
    }
    System.out.println("Finished all threads");
}

这似乎运行良好。 for循环后,等待线程执行完毕结束。

我尝试的第二个选项

private TaskExecutor taskExecutor;

public UpdateBO(TaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
}

private void updateRating() {
        for (int i = 0; i < 10; i++) { // test
            Runnable worker = new ThreadRating(path, i, products.get(i), dao, fileHandler);
            taskExecutor.execute(worker);
        }
    // wait for threads to be finished before you go any further ??
        }

在 xml 文件中我有

<beans:bean id="taskExecutor"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <beans:property name="corePoolSize" value="5" />
    <beans:property name="maxPoolSize" value="10" />
    <beans:property name="queueCapacity" value="25" />
    <beans:property name="waitForTasksToCompleteOnShutdown" value="true" />
</beans:bean>

<beans:bean id="updateBO" class="UpdateBO">
    <beans:constructor-arg ref="taskExecutor" />
</beans:bean>

这是我的问题:

  1. 这两个选项之间有什么区别吗?速度、内存、可能的泄漏?或者它们是一样的,只是写法不同?
  2. 使用网络服务时是否需要关闭池?我知道在第二个选项中我不需要,但是使用 webservice 时是否相同?
  3. 当使用第二个选项时——我应该如何指示等待所有作业完成?在第一个选项中,我只是关闭池并等待完成。但在第二个选项中,代码请求在任务完成之前完成。
  4. executor.execute(worker); - 只是为了澄清。这实际上并没有创建新线程,而是将任务添加到队列中,如果队列已满,它会在代码的这一行等待,直到有空位为止?

谢谢你帮助我理解。

最佳答案

  1. 主要区别:在选项 1) 中,您在每个 updateRating() 调用,在选项 2 中)执行器在部署时创建一次 时间,你给同一个执行者提供新的工作。第二种方法要好得多。

  2. 为什么需要关闭执行器? 创建新的执行者 并关闭它们以等待任务处理完毕是反模式。请记住,执行程序是为了控制系统资源而创建的,并且应该这样对待。 (例如,您有 50 个连接的数据库连接池——因此,为了服务于数据库访问,您创建了 50 个线程的执行程序——以避免超过连接限制。或者您在服务器上有 24 个内核,需要以最佳方式并行工作) .

    而且,正如我在评论中提到的,在某些环境(例如应用程序服务器)中,您通常无权关闭执行程序。此类尝试将产生 SecurityException

  3. 如果你需要等到工作人员完成他们的工作,用Callable而不是Runnable包装每个工作,然后从主线程调用相应的future .get() - 它会阻塞 直到工作完成。支持超时。 Example

  4. 完全正确。线程由执行者自己创建和销毁,当它认为是最好的时候。尝试使用 jvisualvm 监控您的应用,看看它是如何发生的。

关于java - Spring 的多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29492124/

相关文章:

java - 接收从 Observable 发出的项目

Spring - 来自其他 Jar 的存储库为空。如何初始化它?

java - Spring:读取inputStream后如何使用@RequestBody

java - JpaRepository getOne() 获取并更新整个对象

java - 我可以使这个 java pluck() 方法更安全吗?

java - 带有继承方法的Spring hateoas methodOn

java - 使用 UserDetailsS​​ervice 时对数据库进行事务调用

java - Android 应用程序中的菜单操作和总和

c# - System.WIndows.Application 静态成员是线程安全的吗?

java - 使用 run() 而不是 start() 启动线程