Tackle long running tasks with Java threads
Tags: java, concurrency, threads, programming
Published: 2022-10-13 00:04:09

## Introduction

Long running tasks need a special way of handling which user have not to wait until these tasks finished, our get benefit of CPU power and parallel processing long running tasks to finished faster.

## What is a Thread?

A thread is a path of program execution, and JVM allows that multiple paths/threads to work concurrently and not interfere each other.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x754zzxqe98kcgdzo6m6.png)

## Working with threads in Java

As we said before a thread is a path of exaction, and any piece of logic have to run as part of thread as below image.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6t282nlguvrb9hdyhl5p.png)

The Main thread is responsible for executing logic inside main method and execution have to go through line by line and not to move to next until finishing current one. As above image there is a long running task there, and if Main thread is responsible for executing this logic the result will not be shown until this method finish execution, it maybe this method not affect the result at all and making user wait until this method finishes is bad practice.

**Create your own thread**

As part of soliton you can define your own thread and attach your long running logic in and start this path, so we need 2 things:

1. Logic that will run through this path.
2. Thread to act as path.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yz3jjd08a4q6aa1ofjgi.png)

By this there is sperate thread executing the task and main thread continuing in his path and printing the result. But inline implementation or anonymous class is code smell and we have to avoid it, instead in OOP paradigm you can do this


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ivb2cnipuge46je6ytlw.png)

Or you are free to use **functional paradigm** with **Runnable** functional interface and lambda expression as below


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hy33q10cmakzigou0w4z.png)

## Void is not enough

If you notice that Runnable interface has void as return type for run method which can not return a value from that processing, but what if we need a value from that side processing. In this case you have to use Callable interface as below.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kc3s4l3lv7j9gxjsguxk.png)

**Callable** interface has a generic type that you can assign any data type as a return type, but unfortunately you can't assign a **callable** interface to **Thread** class, instead you have to use what called **ExecutorService** class as below


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/to58937oakif72u5ox75.png)

As above we declared ExecutorService that will manage thread execution and will get the result after the thread is finished, and we said that we want this executor to manage up to only 1 thread not more, then by using **submit()** we attach the task we want to execute to the executor. As per our requirement that we asked to run this long running task in separate path and not to block that main thread and also we need a return value from this task. What java did is provided to us **Future** interface, Java tells us that I will take this task and execute it in separate thread, Then take this **Future** reference, when the task finishes you will find your result in, and to access the result you can use **get()** method.

> if you called get() method and the thread not finish the execution yet, the main thread will be blocked until the long running task thread finished its' execution and because of this get() method throws ExecutionException

## ExecutorService for parallel processing

You can also use executor service for parallel processing on huge data as below


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g57kupk8ijdz7zt6k39b.png)

As above we have 3 messages and ExecutorService with 3 threads in its' pool, by constructing 3 task one for each message the executor will assign one task to each thread in his pool and let it start the processing and whenever any one finishes it's execution you can get its' result

> Here we have same number of threads with same number of tasks but if we have larger number of tasks ExecutorService will assign first 3 tasks to its' threads and put the rest of tasks on hold until any of threads finish and assign to another one and so on


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zbn9td66154qvrmnlyo.png)

## ForkJoin Framework

ForkJoin framework is works also as parallel processing but with different approach, it using recursive approach to split the tasks until to reach a predefined batch/size and then start to assign this batch to thread to work on.

you can go with more details and implementation examples [here](https://www.baeldung.com/java-fork-join)

## Resources

- [Guide to ExecutorService](https://www.baeldung.com/java-executor-service-tutorial)

- [ExecutorService video](https://youtu.be/IGAFpko8nBE)

- [Runnable, Callable explanation](https://youtu.be/lQdaLTPPIX4)

- [ForkJoin framework](https://youtu.be/whHaNMmIOgI)

IF YOU LIKED THE POST, THEN YOU CAN BUY ME A COFFEE, THANKS IN ADVANCE.

<a href="https://www.buymeacoffee.com/samehmuh95" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a>