Skip to main content

Posts

Showing posts from November, 2018

Threads in Java - Thread Pools (Part 10)

Server applications are one of the most common use cases in Java. One aspect of server applications is to handle incoming requests and process them. This seems simple to implement but it has its own disadvantages. Since we are creating a new thread for each incoming request, the system would consume more time and resources in creating and destroying threads. This may also lead to the infamous OutOfMemoryError . To deal with such problems, Java provides the concept of Thread Pools. Let us understand this in detail in the below section. Thread Pools When we need to limit the number of threads running in our application, the thread pool proves helpful. There is a performance overhead in starting a new thread and each thread is allocation some stack memory.  Instead of starting a new thread for executing a task concurrently, we can pass the task to a thread pool. As soon as the thread pool has any idle thread, the task is assigned to it and the thread executes the desired tas

Threads in Java - Volatile keyword (Part 9)

Volatile If we mark a variable as "volatile", it means it will be read from the computer's main memory instead of CPU cache and every write will be to the computer's main memory only and not only in CPU cache. When multiple threads operate on non-volatile variables, each thread may copy variables from the main memory to CPU cache for performance reasons. Let us say I have a computer with more than one CPU, each thread may run on a different CPU and hence deal with different CPU caches. source: J enkov With non-volatile variables, there is no guarantee that the data in each CPU cache is the latest (updated) one. Hence, different threads may see different values of the same variable which can cause severe errors. On the other hand, if we declare the shared variable as volatile then it will always be read from the main memory. The problem with threads not seeing the latest value of a variable because it has not yet been written back to main memory by anoth

Threads in Java - Synchronization (Part 8)

We have seen in our previous posts, in a typical Java application, multiple threads run in parallel to complete program execution. This may lead to a situation where multiple threads try to access the same resource simultaneously. This can produce unforeseen and erroneous results. Therefore, a mechanism is required which ensures only one thread can access a resource at a given point of time. Java has the concept synchronization for this mechanism. This allows the programmer to synchronize tasks using synchronized blocks/methods. Synchronized blocks are marked with the keyword "synchronized" . A synchronized block is synchronized on some object. This ensures mutually exclusive access to the shared resource and prevents data race. Only one thread can execute inside a synchronized block at a time. All other threads attempting to enter the synchronized block are blocked until the thread inside the block exits the block. Synchronization also prevents reordering of the co

Threads in Java - Joining (Part 7)

The class java.lang.Thread provides join() method which allows one thread to wait until another thread finishes its execution. If t is a thread object then on calling t.join() will cause the current thread to pause its execution until the thread it joined completes. If there are multiple threads calling the join() method that means overloading on join allows the programmer to specify the waiting period. Like sleep, join also depends on the OS for timing, so we should not assume that join will wait exactly long as we specified. join() method There are three overloaded join methods -  join() - It will put the current thread on wait until the thread on which it is called is done executing. This will throw InterruptedException if the thread is interrupted. join(long millis) - It will put the current thread on wait for the specified time or until the time the thread on which it is called is done executing (whichever is earlier). join(long millis, int nanos) - It is similar to

Threads in Java - start() method and Thread priority (Part 6)

In the previous posts, we have seen that we can start a thread by extending the Thread class or implementing the Runnable interface. In both methods, we override the run() method which is the actual code block where the task assigned to that thread is performed. Even though we override run() method but we start the thread by calling the start() method. Why do we do that? Wouldn't it be straight-forward if we directly call the run() method? In this post, we will discuss this along with the thread priorities. What happens when a method is called? When any method in Java is called, following operations generally take place -  Method arguments are evaluated. A new stack frame is pushed into the call stack. Parameters are initialized. Body is executed. Value is returned and the current stack frame is popped from the call stack. start() vs run() method Even if programmatically we are not creating any thread, For every application, OS will create a default thread t

Threads in Java - Inter-Thread Communication (Part 5)

Sometimes in our applications, we require two or more threads to communicate with each other. One such most common use case is where we have a queue from which one thread is consuming data and the other data is producing data and putting in the queue. Here we have to check if the queue has some data before consuming it. The straightforward method to achieve this polling. In polling, we check if the queue is filled with some data in a loop. If the queue is not empty, we take some action to consume data. This method is inefficient as it wastes CPU cycles. Inter-Thread Communication To avoid polling, Java has a mechanism called inter-thread communication in which one thread sends a notification to the other thread(s) once a certain condition is met. This mechanism has three methods, all of which are in the java.lang.Object class -  wait() - This method pauses the thread and lets it do nothing while a certain condition is true. For e.g., in our producer-consumer problem, the con

Threads in Java - yield(), sleep() and join() (Part 4)

Let's say we want to stop the execution of a thread. How do we do this? There are three methods in the Thread class which can be used to stop the execution of a thread. Let us discuss these methods one by one 1. Yield method Suppose there are two threads A and B. A takes 10 minutes to complete a job while B takes only 10 seconds. At first, A and B both are in the RUNNABLE state then Thread Scheduler gives resources to A to run. Now B has to wait for 10 minutes to do a 10 seconds job. This very inefficient. Wouldn't it be great if we have some way to prevent the execution of A in between so that B can run? Fortunately, yield() method helps us in achieving this.  If a thread calls yield() method, it suggests the Thread Scheduler that it is ready to pause its execution. But it depends upon the Thread Scheduler to consider this suggestion. It can entirely ignore it. If a thread calls yield() method, the Thread Scheduler checks if there is any thread with same/high

Threads in Java - Main Thread (Part 3)

We have discussed that to call a thread we need to create an instance of this thread and call the start() method. But this raises the question, who does this for the very first thread in the Java application? Which thread calls the start() method of the very first thread? This is apparently the chicken-egg problem 😏 but if we go a little deeper, we will find that a thread object is a mere representation of a thread in the program, it does not have information about call stacks and program counter. It only serves as a storage for a pointer to lower level mechanisms that implement threads. Thus, JVM is capable of creating threads without using the Thread class and the thread object can be created later if needed. How does JVM create "main" thread? An instance of java.lang.Thread is not a thread; it can be used to represent a thread of execution in the JVM but the JVM is perfectly capable of creating threads without using the Thread class at all. This is what ha