How to achieve threading ? : for beginners

Reading Time: 3 minutes

Multi-threading

Multi” refers to multiple and “threading” refers to threads as a unit of process. 

So, it is a technique to perform multiple operation within a single process using multiple threads which  are independent in nature and share the same address space. If exception occurs in one thread, it does not affect the others.

Why do we require threads ?

1.Less Completion Time

2. Beneficial for gaming purposes – for example in virtual games like Counter Strike, at a time, different users are running, shooting, etc.

3. When 2 threads working at a time for request and respond, Asynchronous request can be send :

Application                                   Server

4. No need to have as many servlet as request to respond. Suppose 5 clients requesting at a same time, 5 threads of same servlet are created.

C1, C2, C3, C4, C5                              Servlet ( T1, T2, T3, T4, T5)

Hence, above four points concludes that threads are required for the maximum utilization of CPU.

Thread Priority

By default, we have only one thread i.e. main whose priority is 5 ( NORM_PRIORITY). Threads works on the basis of their priority. Priority has range between 1 to 10. 1 is consider as MIN_PRIORITY & 10 as MAX_PRIORITY. If we try to set the priority not in between 1- 10 then an exception is thrown. Higher priority thread has a better chance of getting picked up by thread scheduler. Thread who enters first will be executed, if priority of two threads is same.First, as when priority is the same, threads work on time of their arrival.

Note : Daemon thread has the lowest priority, it’s life depends on the life of User threads so when all user threads die, it runs at the end. A thread cannot be set as daemon, once started. This will throw an exception.

threadObj1.setDaemon(true)

5 is the default priority of threads. We can change their priority by :

val threadObj1 = new Thread(classObject )
threadObj1.setPriority(Thread.MIN_PRIORITY)//1
val threadObj2 = new Thread(classObject)
threadObj2.setPriority(Thread.MAX_PRIORITY)//10
val threadObj3 = new Thread(classObject)
threadObj3.setPriority(3)//3

We can even check the priority of current thread or any other specific thread by:

println(threadObj3.getPriority)
println("Priority of main thread: " + Thread.currentThread().getPriority)

How to achieve threading ?

1.  Extending inbuilt class “Thread :

In main method, we create an instance of Thread class and call it’s start() method which creates a thread and automatically calls run() method in that we can define a specific task to be performed.

class CreateByExtendingThread extends Thread{
//overriding the function run of inbuilt Thread class
override def run(): Unit = {
println("Thread is started and running fine.")
  }
}
object MainObject{
def main(args:Array[String]): Unit = {
val threadObj = new CreateByExtendingThread()
threadObj.start()
 }
}

2.  Implementing inbuilt interface “Runnable” :

Suppose a class needs to extend Thread as well as some other class. As scala or java does not support multiple inheritance so we will implement Runnable interface instead of extending Thread class. This interface works the same as the Thread class.

Thread Sleep

When we wants a thread to wait for sometime then we can put it to sleep for specific milliseconds unless interrupted by using sleep() method which is static. It is not consider as good approach as it is not reliable.

Thread.sleep(500) //i.e.sleep thread for 500ms

Thread Join

When we wants a thread to wait until current thread dies or timeout expires then we use join() method.

threadObj.join()

Thread Lock

Only 1 thread can retain a lock on an object at a time. Other threads trying to acquire that lock will be barred until that lock is released. Synchronization locks an object to perform a task and it is released once completed. This process has the ability to restrict the thread access to any shared resource. In synchronization, we have two types of lock : Object level and Class level. Deadlock situation occurs when first thread waits for an object which is being acquired by second thread and at same time second thread waits for an object acquired by the first.

Why do we require synchronization ?

To prevent

  • Thread Interference
    • when more than one thread uses the same object at the same time.
  • Consistency Problem
    • when changes done by one thread is not visible to other, inconsistency arises.

References :