Skip to content

Java Concurrency Basics

By using Multi-threading or concurrency we can enhance any Program’s performance in a great way. However multi-threading comes with it’s own challenges. Multi-threaded application runs all its thread in the same memory space thereby creating synchronization issues as reading and written of the same memory space is possible. For example, assume that when one thread running on one CPU Core is trying to read a memory location while another thread running on different CPU Core is trying to write it. What will happen now? Which value will the first thread read? Can it read both values partially?

Why use Multi-threading/Concurrency?

Without proper precautions any of the above could happen resulting in unexpected behaviors. If there are many complications then why use them? Here are couple of reasons:

Optimized Resource Usage

While creating any application we need to make sure that our Application will use only the limited resources. Sometimes delay in using any resource is quite large thus our application processing time increases many folds. There are two ways any resource usage could benefit from the concurrency.

Optimizing CPU Time

Lets try to learn via example. Suppose we are creating an application the communicates with a remote server. At any given moment getting instruction and data from the server takes 10 seconds and processing that data and instruction takes 5 seconds. Now lets see what will happen if a single threaded application tries to fetch and execute 3 instructions.

It’s clear that it will take 45 seconds to finish the task. Now lets try to add multi-threading to the environment. Suppose we have one thread that will fetch the data and instruction from the server and other will process it. Checkout what will happen now.

By incorporating multiple threads in our system we effectively reduced the total time our application takes to finish the task by 10 seconds which is a huge difference.

Using Multiple Resources

Again lets try to understand this by having an example. For this example, consider a situation where there are more then one Printers currently connected to the system.

Now if we are using single threaded application we could only use single printer resource for all of the incoming traffic and every time we get a request to print a page, we cannot handle request for new pages. Add some concurrency to the solution and now each printer is managed by a different thread whenever one printer thread is busy other can still take a request to print a new page and thereby utilizing all the resource more effectively.

Fluid User Experience

This is one of the major goal of using multi-threading. We as a application developer never want’s our user to show anything less then perfect user experience. Smoothness of User Interface (UI) is one of the primary factor that affects user experience.

In single threaded environment all the work/task will be performed on the single thread. Assume an application where user can click a few buttons and our application interact with a remote server as well. In this situation, whenever our application is communicating with the remote server, we cannot handle user’s click actions as our application’s single thread is busy doing the task.

Whereas if we have multiple threads we can off-load all the network communication task to a background thread and leaving one thread to handle user’s interaction with the application as creating a much greater user experience. User will also find the UI more responsive even if a quite heavy background task is being performed by the application.

Java Threads Basics

We now know what is the benefit of creating multi-threaded concurrent applications. Next is to understand how to do it. In Java creating and running threads are pretty straight forward.

Threads are created by creating objects of the Thread class like below. Thread class is present in “java.lang.Thread” package. Once we have the thread object we just call start method to start the execution of the thread.

The above code though is complete but it does not tell which task should be performed while this thread is running. So thread has nothing to do thus it will stop right away as soon as thread gets first CPU time.

There a couple of ways you can assign tasks to your thread. Either way you need to implement a run method which will hold your entire logic that will execute when your thread is running. Your thread will start by executing the run method and will finish once run method is finished. The first method is to create a subclass of Thread class and override the run method and the second method is to realize the Burnable(java.lang.Runnable) interface.

Extending Thread Class

In this method we will create a subclass of the Thread class and override the run method. We will provide required functionality to the run method. Execution of the thread will be same as previous, you’ll just call start on the Thread object.

To create and start the thread we need to create an object and call start method on it.

NOTE: Do remember to call the start() method NOT the run() method on the thread otherwise it will not run on a new thread.

As soon as start() method is called, this thread will move to ready state and whenever CPU has time to execute the thread it will start executing the run method of this thread. You can also create an anonymous subclass of the Thread class too and directly pass the run method at the time of initiation of the thread. Same can be done as follows:

Using Runnable Interface

This one is pretty straight forward, you create a class that will implement the Runnable Interface. Runnable interface requires you to give concrete definition of the run method. This Runnable object can be executed by our Thread class. Here is an example of Runnable class.

We have created our concrete Runnable class now we just need to pass this class’s object to our thread and it will start working. This can be done while creating the Thread object while creating a new thread object just pass the Runnable object in parameter and things will work out correctly.

Now we can create and execute new threads as we like fit. This concludes our basics of Java Concurrency. Hope this was of little help.

As always thanks for reading.


Published inJava

Be First to Comment

    Leave a Reply

    Your email address will not be published. Required fields are marked *