Java: Multi-threading and Concurrency Simplified
- Description
- Curriculum
- FAQ
- Reviews
Multi threading in Java is the most essential feature that each and every Java developer should understand and be able to confidently apply it in solving complex programming problems where concurrent execution is a must. With parallel processing there comes a risk, i.e. shared mutability and the ability of the developer to solve concurrency problems.
Thanks to the Java programming language that it makes the mighty multi-threaded application development a cake walk, if you assimilate few keys or core concepts you will be able to confidently design multi threaded applications with ease.
To design multi threaded applications developers need to look at it through a different perspective i.e. change the thinking from serial to parallel and it requires some effort. Keeping this in mind this course contains the essential lectures which can guide you in this regard.
This course was designed keeping the above points in mind and will help you understand these complex problems through simplified and easy to understand examples.
Course contents include
-
Understanding Threads, Priorities, States, Daemon Threads.
-
Thread synchronization using synchronized blocks and locks.
-
Key components of java.util.concurrent package including ForkJoinPool and ForkJoinTask(s).
-
Mock HttpServer to explain how HTTP works and simulate how a typical web server responds to the client requests.
-
ThreadLocal
-
Introduction to distributed locks
-
An overview of how to build scalable applications using Messaging Queues.
-
Introduction to Lambdas and Streams (Coming up)
-
1IntroductionVideo lesson
-
2Single Threaded vs Multi Threaded AppsVideo lesson
-
3Single Threaded App ExampleVideo lesson
Multi-threaded applications normally do parallel processing of tasks where as single threaded applications do one task at a time i.e. If there are two tasks such as T1, T2 they are executed in serial order i.e T1 after T2 or T2 after T1, where as multi threading enables us to execute them simultaneously i.e. T1 along with T2. We can choose single threaded applications when parallel processing is not required example use cases such as simple text editor.
-
4Notes - Single Threaded App ExampleText lesson
-
5True Parallelism vs Logical ParallelismVideo lesson
True parallelism is achieved by assigning tasks to individual CPUs. Where as if there is one CPU and you want to perform multiple tasks in parallel, then CPU will be shared across those tasks for some stipulated time interval, which stands for interleaved execution, and this way of executing the tasks is known as logical parallelism or psuedo parallelism.
-
6Notes - True Parallelism vs Logical ParallelismText lesson
-
7Designing ThreadsVideo lesson
You can create a thread by instantiating Thread class and submit it for execution using the start method. In order to perform a task using thread, you can subclass the Thread class and inside the run method you can perform the corresponding task. One other approach is to implement Runnable interface and submit it for Thread class instance to run it. Later approach is better because sub-classing the thread class means you are extending the Thread functionality which is not the case. Also in case of runnable tasks we can utilise an existing Thread object, so that the same Thread is used for executing multiple tasks.
-
8Designing Threads ExplainedVideo lesson
-
9Notes - Designing ThreadsText lesson
-
10Transform code to achieve parallelismVideo lesson
File copy is an IO intensive activity. Take for example you need to copy 100 files, if you do it in serial manner you are not effectively using the CPU and IO resources. Instead you can make it parallel through Java threads and get optimal performance.
-
11Notes - Transform code to achieve parallelismText lesson
-
12Executor ServiceVideo lesson
Thread creation is a costly activity as it includes creating a separate execution context, stack etc.. Hence we should refrain from creating too many threads for an application. And also creating a thread for each task is not a good idea, instead we can create a pool of threads and effectively utilise them in executing all the task. This could be achieved using ExecutorService in Java. Use the execute method of the ExecutorService to submit a Runnable task, if a thread is available in the pool then it assigns this task to the thread otherwise the task is added to the blocking queue and is kept till a thread is available.
-
13Notes - Executor ServiceText lesson
-
14Stopping Thread in the middleVideo lesson
stop() method of the Thread class could be used to stop the thread in the middle. But this is the dangerous thing to do as it leaves the system in inconsistent state, because we are not giving the opportunity to the thread to rollback or reverse the actions that it has taken. And hence the stop method is deprecated.
Correct approach would be to interrupt() the thread and then it is up to the thread to consider it. A thread can check if it was interrupted or not using interrupted() method. If interrupted() we can design the thread in a way that it reverses the actions it has performed and then stop.
sleep() method of the thread class is used to block the thread for the given time interval in milliseconds.
-
15Notes - Stopping Thread in the middleText lesson
-
16Thread StatesVideo lesson
-
17Notes - Thread StatesText lesson
-
18Thread PrioritiesVideo lesson
-
19Notes - Thread PrioritiesText lesson
-
20Internal System Threads and ThreadGroupVideo lesson
-
21Notes - Internal System Threads and ThreadGroupText lesson
-
22Daemon ThreadsVideo lesson
-
23Notes - Daemon ThreadsText lesson
-
24Callable TaskVideo lesson
Unlike Runnable, Callable interface allows us to create an asynchronous task which is capable of returning an Object. Create a Callable task and submit it for ExecutorService which returns the Future object. We can use this Future object to get the result once the task is completed.
-
25Notes - Callable TaskText lesson
-
26Pattern search in folder - Serial approachVideo lesson
-
27Pattern search in folder - Parallel approachVideo lesson
-
28Notes - Pattern Search in folderText lesson
-
29Problem Set - 1Video lesson
-
30Problem Set - 1 - SolutionText lesson
-
31Need for SynchronizationVideo lesson
When an object is modified through multiple threads we need to synchronize the operation to make it threadsafe or re-entrant. If it not taken care then it might lead to inconsistent results.
-
32Synchronized methodsVideo lesson
To make a method re-entrant we might declare it as synchronized. When a method is synchronized the corresponding object is locked before a thread can enter into the method. This can solve concurrency problems to some extent but it is not a good solution.
-
33Synchronized in case of static membersVideo lesson
-
34The Problem with Synchronized Method and Solution with Synchronized BlockVideo lesson
Instead of making a method synchronized, we can use the synchronized block which allows us to retain the lock only for a specific portion of code instead of the entire method. This is at times a better solution as synchronized method doesn't solve a class of problem where multiple method calls need to be atomic instead of one single method.
-
35Notes - Thread SynchronizationText lesson
-
36Deadlocks and solution with lock sequencingVideo lesson
-
37Notes - Deadlocks and solution with lock sequencingText lesson
-
38Reentrant LocksVideo lesson
ReentrantReadWriteLock allows us to obtain two different kinds of locks,
- readLock() - If there are other readLock request they will also acquire the lock till the writeLock request is obtained. Once writeLock request is obtained all subsequent requests should wait till writeLock is unlocked.
- writeLock() - Mutually exclusive.
read write locks are preferred over synchronized methods due to shared read and their ability to go beyond a method with lock acquired.
-
39Notes - Reentrant LocksText lesson
-
40Problem Set - 2Text lesson
-
41Problem Set - 2 - SolutionText lesson
-
42Thread Signaling Using wait and notifyVideo lesson
-
43Producer and Consumer ProblemVideo lesson
-
44Notes - Producer and Consumer ProblemText lesson
-
48BlockingQueue and revised producer and consumer problemVideo lesson
-
49Notes - BlockingQueue and revised producer and consumer problemText lesson
-
50PriorityBlockingQueueVideo lesson
-
51Notes - PriorityBlockingQueueText lesson
-
52Fork Join FrameworkVideo lesson
-
53Notes - Fork Join FrameworkText lesson
-
54SemaphoreVideo lesson
-
55CountDownLatchVideo lesson
-
56CyclicBarrierVideo lesson
-
57Atomic Types (AtomicInteger, AtomicBoolean....)Video lesson
External Links May Contain Affiliate Links read more