SLC S22 Week5 || Threads in Java: Life Cycle and Threading Basics

We got to week 5 of @kouba01's java class, getting closer and closer to the end of this season, if you haven't joined yet but you want to, follow his work here SLC S22 Week5 || Threads in Java: Life Cycle and Threading Basics.


New Project (1).png
Image taken from Pixabay

Before we start I wanted to leave a small review, this was one of the hardest classes I've taken here, and it was one of the very few classes that takes a person through many things from basic ones to more advanced ones. Now I understand why @kouba01 won one the best teacher awards, he clearly is in the top by far.


1.png

  • Write a program that demonstrates how thread priorities affect execution order. Create three threads and assign them the priorities MIN_PRIORITY, NORM_PRIORITY, and MAX_PRIORITY. Run the threads and observe the execution order. Provide an explanation of whether the thread priority influences their execution order and why.


image.png

Straight to the point, we start with the constructor so we can name our threads right from the creation without needing to use setName() and we override the run method so we can print each of the threads.

In the main we simply create each thread and it's custom name, added - -- --- so we can see them better in the console. Created and named now we need to setup their priority using setPriority and the corresponding values MIN/NORM/MAX_PRIORITY.

All that's left is to call the start method for each one and we are ready to run the code.

Below you'll see a GIF with a few runs of the code, you can observe the console and the values being different each time.


javaw_Z81wIKveje.gif

Each run outputs a different order because setting the priority doesn't guarantee the priority for a thread, everything is scheduled by the thread scheduler which works differently based on the OS.


spacer.png






2.png

  • Develop a program that intentionally causes a deadlock using synchronized methods. Design a scenario where two or more threads attempt to acquire locks on shared resources in reverse order, leading to a deadlock. Provide a detailed explanation of how the deadlock occurs and suggest strategies to prevent it.

So as far as I understand to create a deadlock we need to have at least two threads that are blocked one waiting for the other to release the resources. After doing some research the simplest way to do this is to have 2 classes each one with it's own method that gets called in the other class, like this:

The first test class:


image.png

And the second one:


image.png

Also here is the main:


image.png

We created the two objects for this example, after that we need to create the threads where we use Runnable to make sure this is being executed by a thread and also we invoke the run method to execute the thread logic. Now if we run the code we get this output.


javaw_j2ixxYk0sY.gif

So to describe the process, we have the two threads and two resources, both resources use synchronized methods with this we make sure only one thread can lock a resource at a given time, like two threads that try to get the two resources in opposite order.


spacer.png






3.png

  • Create a program where multiple threads count from 1 to 100 concurrently. Ensure that the numbers are printed in the correct order without conflicts, even though the counting occurs in parallel. Describe the mechanisms (e.g., synchronization) used to maintain the correct sequence.

Not sure if I understood this correctly, so each time we count it the counting needs to be done by a different thread.

We start by creating the variables for counting and threads, we create 5 threads for this example and we start them.


image.png

After that we use the threadId to give a unique id to the threads and we use it to control which thread takes control to count and print the value. lock is used to ensure that only one thread can count, when the thread enters the synchronized block it prevents other threads from taking control.


image.png

Let's see a live run:


javaw_iLrRCgvAIw.gif

As you can see each count is made on a different thread.


spacer.png






4.png

  • Write a program that uses a thread pool to process a list of tasks efficiently. Implement a set of simple tasks (e.g., displaying messages or performing basic calculations) and assign them to the threads in the pool. Explain how thread pools improve performance compared to creating threads for each task individually.

We need to stat by importing the classes/libraries we are going to use in this example, ExecutorService is used for methods that manage and control the threads, while Executors is used to create pre-configured pools.

ExecutorService threadPool = Executors.newFixedThreadPool(4); allows us to create a thread pool with 4 threads.

Now we need to create the tasks, starting with the print one.


image.png

We are going to use this task to simply print a message, the constructor takes a message to be printed, while in Thread.currentThread().getName() we are also printing the name of the thread that executes the print of the message.

For the second task we'll perform some calculations, we define the variables and the constructor (accepts two values of int for the calculation), all that needs to be done in the end is to override the run to do the calculations and show it with the thread names.


image.png

With the tasks being ready we need to head over to the main and add tasks to the thread pool.


image.png

With the tasks created we need to submit each one in the created thread pool and we also need to make sure that once we are done we shutdown the pool, this way we release the resources used.

Let's check a live example, you can see that the threads/task link changes as we run the code.


javaw_lMOVnVWOWi.gif


spacer.png






5.png

  • Write a program where multiple threads read different parts of a file simultaneously. Divide the file into distinct segments, assign each segment to a thread, and print the content read by each thread. Explain the logic used for dividing and assigning file segments to avoid conflicts and ensure efficiency.

There are different ways to approach this, the easiest one that comes to my mind is to split the text in as equal as possible parts and submit each segment as a task to the thread pool. Now the splitting part can be done from word to word but that's hard so we gonna divide it by lines, each thread takes a number of lines that will bread.

First I took a random text paragraph from the internet and pasted it two times in a text.txt so we have plenty of text to work with. It looks like this:


image.png

Now let's handle the file, we start with the constructor that uses the attributes to get the lines of text from where it starts and where it ends.
We override the run method that will allow us to print each thread with it's lines of text.


image.png

Now for the main part, we set the file that we are going to read from, also set a number of threads in a variable and use a try-catch block to read the lines from the file to get a total number, then we distribute each line as evenly as possible between the number of threads so each one gets closely the same amount of work.

Once this is done, we need to create the thread pool and loop through the threads printing each thread's line. Once we are in the loop we calculate where the end of current's thread should be, we execute until that end, then the current end becomes the current start from where we loop again, calculate the end again and so on until we finish all the segments.

In the end we shut down the pool and also use a catch block in case the file is not being found.


image.png

A live example:


javaw_Jjys0UVlti.gif


spacer.png






6.png

  • Develop a program simulating a bank system where multiple threads perform deposits and withdrawals on shared bank accounts. Use synchronization to ensure thread safety and prevent issues such as race conditions. Provide an explanation of the techniques used to maintain data integrity in the presence of concurrent threads.

Since we are going to perform tasks on a shared resource we need to use synchronized methods, let's start by creating them first. We need one for the deposit task and one for the withdraw, both will update the value of balance, an attribute declared and used in the constructor.


image.png

For the deposit method we simply add the amount to the balance and print the new balance, while for the withdrawal we are going to also check if the balance is bigger than the amount requested for withdrawal, we can't withdraw more than we have in balance.

We also create a getBalance() method but this one doesn't need to be synchronized because it just returns the amount in balance, doesn't change it in any way.

Now for the main part we create the BankAccount with a starter balance and we manual manage each thread to do tasks with our shared account. Once threads are ready we start them and let them work, also while researching this I found there is .join() method that can be used to block the caller thread until current thread completes its work.


image.png

Now for this example it's enough to manage manually each thread but if the work amount increases a threadpool would increase efficiency (efficient resource management).

A live example:


javaw_yv3CNZWbTg.gif


spacer.png





That was it for this homework/challenge, in the end I'd like to invite @r0ssi, @mojociocio and @titans. This was one of the hardest tasks I've seen, if not the hardest but it was fun, haven't worked with threads before, I always avoided them.

Until next time, wishing you a great day!

Sort:  
Loading...

Coin Marketplace

STEEM 0.22
TRX 0.24
JST 0.037
BTC 102892.57
ETH 3257.73
SBD 4.75