春天的多线程

Eli*_*ane 10 java spring multithreading threadpool threadpoolexecutor

我想进入春季多线程,我几乎没有问题.

我在ThreadRating类中有runnable方法.现在我不确定使用它的最佳方式.

选项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");
}
Run Code Online (Sandbox Code Playgroud)

这似乎运行良好.在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 ??
        }
Run Code Online (Sandbox Code Playgroud)

在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>
Run Code Online (Sandbox Code Playgroud)

以下是我的问题:

  1. 这两个选项有什么区别吗?速度,记忆,可能的泄漏?或者他们是否只是以不同的方式写的?
  2. 使用webservice时是否需要关闭池?我知道在第二个选项中我没有必要,但使用webservice时是否相同?
  3. 当使用第二个选项时 - 在完成所有工作之前,我应该如何判断等待?在第一个选项中,我只是将游泳池关闭并等待完成.但是在第二个选项中,代码请求在任务完成之前完成.
  4. executor.execute(worker); - 只是澄清一下.这实际上并不是创建一个新线程,而是将任务添加到队列中,如果队列已满,它会在代码中的这一行等待直到有空位?

谢谢你帮我理解.

Ale*_*you 6

  1. 主要区别:在选项1)中,您在每次updateRating()调用时创建新的执行程序 ,在选项2中,执行程序在部署时创建一次,您使用新作业向同一个执行程序提供.第二种方法要好得多.

  2. 为什么需要关闭执行程序?创建新执行程序并将其关闭以等待处理任务是反模式.请记住,创建执行程序是为了控制系统资源,应该对其进行处理.(例如,您有50个连接的数据库连接池 - 所以为DB访问提供50个线程的执行程序 - 以避免连接限制超过.或者您在服务器上有24个核心并且需要以最佳方式并行化工作) .

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

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

  4. 绝对正确.线程由执行器本身创建和销毁,当它认为是最佳时间时.尝试使用jvisualvm监控您的应用,看看它是如何发生的.