Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multithreading in spring

I am trying to get into spring multithreading and I have few questions.

I have runnable method in ThreadRating class. Now I am not sure about the best way of using it.

option 1 I found:

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");
}

This seem to be running fine. After the for loop, it waits until threads are finished and ends.

Second option I tried

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 ??
        }

And in xml file I have

<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>

And here are my questions:

  1. Is there any difference between these two options? Speed, memory, possible leaks? Or are they the same just written differently?
  2. Do I need to shutdown the pool when using webservice? I know that in the second option I don't have to, but is it the same when using webservice?
  3. When using second option - how should I tell to wait there until all jobs are finished? In the first option I just shut the pool down and wait to finish. But in the second option the code request is finished before the tasks are completed.
  4. executor.execute(worker); - just to clarify. This is not actually creating a new thread, but it adds task to a queue and if the queue is full it waits right on this line in the code until there is free place?

Thanks for helping me understand.

like image 571
Elis.jane Avatar asked Apr 07 '15 12:04

Elis.jane


People also ask

How does multithreading work in Spring Batch?

Multithreaded steps. By default, Spring Batch uses the same thread to execute a batch job from start to finish, meaning that everything runs sequentially. Spring Batch also allows multithreading at the step level. This makes it possible to process chunks using several threads.

Is spring boot rest controller multithreaded?

It is multithreaded. @Humberd Are you sure you tried requests from separate sessions? If you open different tabs on same browser they will share same session so same thread.

How multithreading works in Microservices?

Rather than building one service for an entire application, multiple loosely coupled services are created, with each being responsible for a single feature. Depending on the load on features, each service can be scaled up or down individually.

Is CompletableFuture multithreaded?

The CompletableFuture, was introduced in Java 8, provides an easy way to write asynchronous, non-blocking and multi-threaded code.


1 Answers

  1. Main difference: in option 1) you create new executor on every updateRating() call, in option 2) executor is created once on deployment time, you feed the same single executor with new jobs. Second approach is much better.

  2. Why do you need to shut down the executor? Creating new executors and shutting them down to wait until task is processed is antipattern. Remember, that executors are created in order to control system resources and should be treated such. (E. g. you have DB connection pool of 50 connections - so to serve DB access you create executor of 50 threads - to avoid connection limit exceed. Or you have 24 cores on server and need to parallelize work in the best possible way).

    And, as I mentioned in comment, in some environments (such as app servers) you often have no rights to shut down executor. Such attempt will produce SecurityException.

  3. If you need to wait until workers finish their jobs, wrap every job with Callable instead of Runnable, then from main thread call corresponding future.get() - and it will block until job finishes. Timeouts are supported. Example

  4. Absolutely right. Threads are created and destroyed by executor itself, when it thinks is best time to. Try to monitor your app with jvisualvm to see how it happens.

like image 101
Alex Salauyou Avatar answered Oct 23 '22 17:10

Alex Salauyou