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:
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.
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.
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.
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.
The CompletableFuture, was introduced in Java 8, provides an easy way to write asynchronous, non-blocking and multi-threaded code.
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.
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
.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With