10 Things about Threads Every Java Programmer Should Know

Thread in Java is one of those topics which always confuse beginners but given the importance and strength it provides to the Java language, it's very important for every Java developer to learn and understand the fundamental concept of multi-threading and basic points about Thread in Java. I had started thread programming in Java by animating a couple of words in Applets, that was an amazing experience to code animation, but after spending almost 10 years on developing core Java applications and I am still discovering things about threading and concurrency. My first program which involves Thread had three words dropping from each corner of the screen and I was excited to see that animation driven by Java thread.

The main point is, no matter which domain you are working multi-threading will always be there. It's also an important part of any Java interview, you can see types of questions asked in my post top 10 Java thread, concurrency, and multi-threading questions.

In this article, I am listing down some important points related to Thread in Java, particularly about java.lang.Thread class to revise things for all of those Java programmers, who know Threading but a good exploring point for someone who has started picking pace in multi-threading.



10 Things about Thread in Java

java.lang.Thread class but JVM plays an important role in all Thread activities. Thread is used to execute tasks in parallel and this task is coded inside the run() method of the Runnable interface. You can create Thread in Java programming language by either extending Thread class, implementing Runnable, or by using the Executor framework in Java. Remember Runnable doesn't represent Thread actually it's a task that is executed by Thread. Read more about extends Thread vs implements Runnable here.




1. Independent Path of Execution
Thread in Java represents an independent path of execution. (classic definition but I still like it). Thread is represented by

2. Thread States
During its lifetime thread remains on various Thread states like NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING which describe what the thread is doing. NEW means thread is just created but not yet started, RUNNABLE means thread is started but waiting for CPU to be assigned by the thread scheduler. BLOCKEDWAITING and TIMED_WAITING means the thread is not doing anything instead it's been blocked and waiting for IO to finished, class or object lock, or any other thread, etc You can also see these Java Multithreading and Concurrency courses to learn more about Threads in Java. 


10 Things about Threads Every Java Programmer Should Know



3. Daemon vs User Threads
There are two kinds of Thread in Java daemon or non-daemon (also called user threads). Java programs run until there is at least one non-daemon thread that exists. The first non-daemon thread started by JVM is the main thread that is created by JVM and responsible for executing code inside the main method in Java. This is called the "VM thread" in HotSpot Virtual Machine. 

Any thread created using java.lang.Thread start() methods from the main thread is by default non-daemon but you can make it daemon by calling the setDaemon(true) method. A newly created thread in Java inherits daemon property from the thread which creates it. Since main thread is non-daemon, any thread created by it by default remains non-daemon.



4. Thread Priority and Name
Every Java thread has priority and name. You can set priority and assign meaningful name while creating an object of java.lang.Thread class in Java. its recommend practice to give every thread a meaningful name while creating it , it helps later when you debug your Java program or take thread dump for analysis. 

Otherwise, Java will give your Thread default name like "Thread-number" if Thread is created using java.lang.Thread or "pool-number-thread-number" if Thread is created using ThreadFactory. In Java higher, priority thread gets preference in Execution over the lower-priority thread. you can check priority by using methods like getProiroty() from the thread class.


5.Executor Framework
The creation of a thread is a time-consuming job so having a Thread pool for performing tasks concurrently is a modern-day requirement of performance and scalability. Java 5 provides Executor framework which encapsulates task of creating and managing thread from application code. Consider using Thread pool if your application requires to handle the load. In web and application server manages this thread pool because each request is processed in its own thread.


6. Pausing a Thread
The Thread.sleep() method is used to pause the thread for a specified duration. It is an overloaded method defined in java.lang.Thread class. On the other hand Thread.join() is used to wait for another thread to complete its task before running and yield() method is used to relinquish CPU so that other threads can acquire it. See the difference between sleep, wait, and yield for details.


7. Inter-Thread Communication
The wait() and notify() methods are used to communicate between two threads i.e. for inter-thread communication in Java. Always check the condition of the wait() method in the loop and call them from a synchronized context. wait() is a method that is defined in the object class, and puts the current thread on hold and also releases the monitor (lock) held by this thread,  while notify() and notifyAll() methods notify all threads waiting on that monitor. 

There is no guarantee which thread will pick up by the thread scheduler and given CPU to execute because of notification. To learn more about how to use the wait, notify, and notifyAll method to achieve inter-thread communication, see my post about solving the producer-consumer problem in Java using the wait and notify method.

inter thread communication in Java.




8. Thread Scheduler
Thread scheduling is done by Thread Scheduler which is platform-dependent and stays inside JVM. There is no known way to control thread scheduler from Java and many of thread related decision is done by scheduler like if there are many threads is waiting then which thread will be awarded CPU.


9. Thread Alive
Thread.isActive() method is used to check whether a thread is active or not. A thread is said to be active until it has not finished either by returning from the run() method normally or due to any exception. Thread.holdsLock() method is used to check if a thread holds a lock or not. See how to check if the thread holds a lock or not for more details.

10. Thread Stack
Every thread in Java has its own stack, which is used to store local variables and method calls. Size of this stack can be controlled using -XX:ThreadStackSize JVM option e.g. -XX:ThreadStackSize=512.

11. Task
Java 5 introduced another way to define tasks for threads in Java by using the Callable interface. It's similar to the Runnable interface but provides some more capability like it can return the result of task execution, which was not possible in Runnable because the return type of run() method was void. 

Like its predecessor, it defines a call() method which can return Future<T> object, you can call the get() method on this object to get the result of task execution. To learn more about Callable, please see the difference between Runnable and Callable interfaces in Java.

12. Interruption
Java provides an interrupt() method to interrupt a thread in Java. You can interrupt a running thread, waiting for a thread, or sleep thread. This is the control Java provides to prevent a blocked or hanged thread. Once you interrupt a thread, it will also throw InterruptedException, which is a checked exception to ensure that your code should take handle interrupts


13. Locking
Java provides two ways to achieve mutual exclusion in your code, either by using a synchronized keyword or by using java.util.concurrent.lock implementations. Former is the more popular and oldest way to achieve mutual exclusive code but  Lock interface is more powerful and provides fine-grained control and is only available from Java 5, Tiger. 

You can use a synchronized keyword to either make an entire method mutually exclusive or only a critical section by declaring a synchronized block. Any thread needs to hold monitor or lock, required by that critical section in order to enter into synchronized block or method, they release that lock, once they exit, either normally or abruptly due to an error. 

Acquisition and release of the monitor are done by Java itself, so it's safe and easy for Java programmers, on the other hand, if you decide to use the Lock interface, you need to explicitly acquire the lock and release it, this requires more caution. A popular idiom is to release the lock in finally block. See my post on how to use ReentrantLock in Java for code examples and few more details.

14. Start vs Run
One more thing to know about Thread in Java is that it's not started when you create an object of Thread class like:
Thread t = new Thread();

In fact, thread is started when you call the start() method of java.lang.Thread class e.g. t.start() will start the thread. It puts your thread in RUNNABLE state and when the thread scheduler assigns the CPU to this thread, it executes the run() method.  By default run() method Thread class is empty, so you need to override it to do some meaningful task.

That's all on important points related to Thread in Java. You can also suggest points, which you think it been missed here and I will include them in this list to make it more comprehensive and useful. I will also aim to keep it updated with more points once and when I recall or get aware of any stuff related to threads in Java. Last but not least Effective Java book also got some good advice about synchronization and threads, worth reading for all kinds of Java developers.


7 comments:

  1. Great article, can you elaborate more about OS threads that actually executing the java threads? Which java thread states are assigned by the OS threads?

    ReplyDelete
  2. One more thing about java threads are that they are unpredictable, you can not say when your thread is started or running, its all governed by thread scheduler.

    ReplyDelete
  3. I guess that the above is already been covered in above article ..

    ReplyDelete
  4. Another point would be on how to deal with exceptions ( mostly unchecked exceptions ) in your concurrent code. What happens to your thread if an unchecked exception is thrown by the run method implementation? Is your thread going to die?
    These checks can save you from surprises at runtime.

    ReplyDelete
  5. Can we stop a thread and restart the thread, instead of creating new threads everytime?

    ReplyDelete
    Replies
    1. Hello Vijay, yes you can put a Thread on sleep and reuse it. This is what most of thread pool do instead of creating new threads, which obviously take more time. You can see how to pause thread in Java for more details.

      Delete

Feel free to comment, ask questions if you have any doubt.