|
1. Thread Pool Executor: A thread pool is a group of worker threads that can be reused for executing multiple tasks. The ThreadPoolExecutor class is the most commonly used executor in Java. It allows you to submit tasks for execution and manages the lifecycle of the worker threads. You can configure the size of the thread pool, keep track of completed tasks, and handle rejected tasks. 2. ForkJoinPoolExecutor: This executor is designed for performing fork-join operations. It breaks down a task into smaller subtasks and then combines their results. It is useful when you have a recursive algorithm that can be parallelized. 3. RejectedExecutionHandler: This handler is used to handle tasks that cannot be executed due to a lack of resources, such as insufficient memory or too many pending tasks.
|
|
As with deadlock, livelocked threads are unable to make further progress. However, the threads are not blocked — they are simply too busy responding to each other to resume work Deadlock: situation where nobody progress, doing nothing (sleeping, waiting etc..). CPU usage will be low;
Livelock: situation where nobody progress, but CPU is spent on the lock mechanism and not on your calculation;
Starvation: situation where one procress never gets the chance to run; by pure bad luck or by some of its property (low priority, for example);
Spinlock: technique of avoiding the cost waiting the lock to be freed.
Java-Example for a deadlock: Thread A : waits for lock 1 Thread B : waits for lock 2 Thread A : holds lock 1 Thread B : holds lock 2 Thread B : waits for lock 1 Thread A : waits for lock 2
Java-Example for a livelock:
https://slideplayer.com/slide/3281719/
1. SimpleAsyncTaskExecutor: · This is a basic implementation of the TaskExecutor interface. · It creates a new thread for each task, making it suitable for short-lived asynchronous tasks. · Not recommended for heavy workloads due to the overhead of creating new threads.
@Bean public AsyncTaskExecutor asyncTaskExecutor() { return new SimpleAsyncTaskExecutor(); }
2. ThreadPoolTaskExecutor: · This implementation allows you to configure a pool of worker threads. · It's more efficient than SimpleAsyncTaskExecutor for handling a large number of tasks. · You can configure properties like the core pool size, max pool size, and queue capacity.
@Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(25); return executor; }
3. CommonsRequestLoggingFilter: · This is a filter that logs details of each HTTP request. · It's not a thread pool per se, but it can be configured to use a thread pool for logging purposes, especially when logging requests can be time-consuming.
@Bean public CommonsRequestLoggingFilter requestLoggingFilter() { CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); filter.setTaskExecutor(new SimpleAsyncTaskExecutor()); return filter; }
4. WorkManagerTaskExecutor: · This is an implementation that adapts a Java EE WorkManager to the Spring TaskExecutor interface.
@Bean public WorkManagerTaskExecutor workManagerTaskExecutor() { return new WorkManagerTaskExecutor(); }
These are just a few examples, and Spring Boot provides flexibility for configuring and customizing thread pools based on your application's requirements. Depending on your use case, you might choose a different implementation or configure properties like core pool size, max pool size, and queue capacity accordingly
FixedThreadPool: · The FixedThreadPool creates a fixed number of threads and reuses them to execute tasks. · It's suitable when you want to limit the number of concurrent tasks. · ExecutorService executor = Executors.newFixedThreadPool(5);
2. CachedThreadPool: · The CachedThreadPool creates new threads as needed and reuses existing ones. · It's suitable when the number of tasks can vary, and you want to reuse threads to avoid the overhead of thread creation. · ExecutorService executor = Executors.newCachedThreadPool();
3. ScheduledThreadPool: · The ScheduledThreadPool is designed for scheduling tasks to run after a certain delay or periodically. · It's suitable for scenarios where tasks need to be executed at fixed intervals or with a delay. · ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
4. SingleThreadExecutor: · The SingleThreadExecutor creates a single worker thread to execute tasks sequentially. · It's useful when tasks must be executed in a specific order or when you want to ensure that only one task is executed at a time. · ExecutorService executor = Executors.newSingleThreadExecutor();
These thread pool implementations are part of the Executors utility class in the java.util.concurrent package. While these are convenient for many use cases, in a Spring Boot application, you might prefer to use the ThreadPoolTaskExecutor bean for more fine-grained control and integration with the Spring ecosystem, as mentioned in the previous response. The ThreadPoolTaskExecutor allows you to set properties such as core pool size, max pool size, and queue capacity to tailor the thread pool to your application's specific needs.
1. Visibility: · The volatile keyword ensures that any thread reading a volatile variable sees the most recent modification made by any other thread. · Without volatile, changes made by one thread may not be visible to other threads. 2. Atomicity: · The volatile keyword guarantees atomic reads and writes for the variable. However, it does not provide atomicity for compound actions (e.g., check-then-act). 3. No Caching: · volatile variables are not cached in thread-local memory. When a thread reads a volatile variable, it always reads the variable's current value from main memory.
Atomic Variables
that support atomic operations (read-modify-write operations) without the need for explicit synchronization. |
||
package
com.govtech.demo.console;
Blocking vs. Non-Blocking: ·
Future: Primarily relies on blocking operations.
You use the ·
CompletableFuture: Encourages non-blocking
programming. It provides methods like
Differences between Future and CompletableFuture
|
||
|
||
|
||
wait() and sleep() are both important methods for managing concurrency, but they serve distinct purposes. wait() is used for inter-thread communication and synchronization, while sleep() is used to introduce pauses or delays in thread execution.
Thread Safety : that allows it to be used safely by Multiple Threads without causing any unexpected behavior or data corruption
Issues with Shared Resources: Race condition, Deadlock and data Inconsistency
How to make ThreadSafe
Immutable Objects
Synchronize shared Resource Access
In a chess game, continuous repetition will end up match draw,