MultiThreading
S.No. | Process based Multitasking programming | Thread based Multitasking programming |
1 | A process is essence of program that is executing which running parallel | Thread is a such part of multithreaded program which defines separate path for execution |
2 | It allows you to run java compiler and text editor at a same time. | It doesn’t support java compilerand text editor run simultaneously.Both have performed different tasks |
3 | In process based multitasking a process or a program is the smallest unit. | In thread based multitasking a thread is the smallest unit. |
4 | In process based multitasking a process or a program is the smallest unit. | In thread based multitasking a thread is the smallest unit. |
5 | Program is a bigger unit. | Thread is a smaller unit. |
6 | Process based multitasking requires more overhead. | Thread based multitasking requires less overhead. |
7 | Context switching difficult and slow | Context switching is easy and fast |
8 | Process requires its own address space. | Threads share same address space. |
9 | Here, it is unable to gain access over idle time of CPU. | It allows taking gain access over idle time taken by CPU |
10 | It is not under control of java. | It is totally under control of java. |
11 | Process to Process communication is expensive | Thread to Thread communication is not expensive. |
Thread Life Cycle
isAlive() : Method is used to check whether the thread is alive or dead.
Yield(): When you called yield() method on the running thread. Running thread will give a chance to another thread which is in ready to run state. i.e, Running thread will be placed back to ready to run state. Some other thread which has the highest priority will be moved from ready-to-run state to running state but JVM doesn’t guarantee.
Join(): When you call join method on the threads then the join thread will be completed first and then parent thread from where the other threads are started. Example, from main method 2 child threads t1 and t2 are started. When I call join method on t1 and t2 then main thread wait until child thread finishes it task.
Daemon Threads: Are the service threads. Daemon threads live as long as dependent threads are running. You can make any thread as deamon by using the following methods.
Void setDaemon(boolean);
Boolean isDaemon(); We can check whether the thread is daemon thread or not.
Threads can created in 2 ways :
- By extending thread class
- By implementing runnable interface.
Implementing through runnable interface is best option. When you extend the thread class, we don’t have a chance to extend any other class, bcoz no multiple inheritance with java classes, where as when you implement runnable interface we can extend some other class also. And when you extend thread classes all the implemented methods in the thread class will be loaded in to the memory. Where are when you implement runnable interface we don’t get such problem.
Scheduling Algorithm:
- Primitive Scheduling Alg : Suppose 2 threads t1 and t2 enter into ready to run state with the priorities 4 and 6 respectively. Now T2 gets the CPU time, because of it has highest than T1. Now T2 is running and t1 is in ready to run state. Another thread called t3 with priority 9 and entered in to ready to run state. And t3 has highest priority than the running thread. And then t2 will be preempted and t3 enter into running state.
- Time slice or Round Robin Alg : In this alg, each thread will be given fixed amount of time and CPU time will be allocated for each thread based on FCFS(First come First Serve) or Primitive Algorithm and thread will be running state for specified quantum time. After the time is over thread will be back to ready to run state and another thread will be entered in to running state and so on…
Dead Locks :
Example : Thread t1 which is holding resource r1 is waiting for resource r2 and thread t2 which is holding a resource R2 and waiting for resource R1. T1 releases the resource R1 after serving R2 and T2 releases Resource R2 after serving R1. They won’t release the resource and they won’t get the resource also. Simply T1 and t2 will be blocked. No chance to move from out of block state. This situation is called dead lock.
Thread Priorities: We can give an integer number ranging from 1 -10 as priority to the threads. They are 3 constraints defined inside the thread class.
- MIN_PRIORITY – 1
- NORM_PRIORITY -5
- MAX_PRIORITY – 10
We have two methods to find the priority of the thread and to change the priority of the thead.
1)int getPriority()
2)void serPriorities(int)
Synchronization: In multi-threading environment when all threads are accessing the object concurrently. Some time we can get inconsistent results. To avoid inconsistent results, I don’t want to allow all the threads to access the object concurrently. I want to allow one-by-one to access the object. This is known as Synchronization.
When you synchronize the object, object will be locked and will be monitored. Threads which would like to use locked objects will enter in to the monitor and uses the locked object. After using the object, come out of the monitor. The threads outside the monitor unable to access the locked objects. We can do the synchronization using the modifier called as synchronize modifier. We can use this modifier in 2 ways,
- Method level synchronization
- Block level synchronization
- Synchronized modifier is not allowed for classes, interfaces and variables.
- When you call any synchronized method with an object – that object will be locked. Then no other threads use that object.
- When you are using block level synchronization, you should pass any object to the block. And that passed object will be synchronized or locked.
- In method level synchronization – Object of the class which contains synchronized method will be locked. Where as in block level synchronization, the objects which we are passing to synchronized block (any object ) will be locked.
- In case of synchronized method, lock is acquired by thread on object when it enter method and released when it leaves method. On the other hand in case of synchronized block, thread acquires lock when they enter synchronized block and release when they leave synchronized block.
Programs :
public class SystemThread { public static void main(String[] args) { int x = 0; Thread t1 = new Thread(); t1.setName("Java"); Thread t2 = new Thread(); t2.setName("Sql"); for (int i = 0; i <= 10; i++) { System.out.println(t1.getName() + x); try { t1.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(t2.getName() + x); x++; } } }
By extending Thread
public class ThreadExamp1 { public static void main(String[] args) { new MyThread1("java"); new MyThread1("Sql"); } } class MyThread1 extends Thread{ static int a=1; String name; MyThread1(String name){ setName(name); start(); } public void run(){ for(int i=0;i<10;i++){ a++; System.out.println(getName()+" "+a); try { Thread.sleep(5000); //wait(5000); } catch (InterruptedException e) { } } } }
By implementing Runnable
public class RunnableExample { public static void main(String[] args) { new MyRunnable("java"); new MyRunnable("sql"); } } class MyRunnable implements Runnable{ int a=0; Thread t; MyRunnable(String name){ t = new Thread(this,name); t.start(); } public void run() { for(int i=0;i<10;i++){ System.out.println(t.getName()+" "+i+" "+a); try { t.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } a++; } } }
Synchronization Example
public class SynchronizationExample { public static void main(String[] args) { IncrementOper inc1 = new IncrementOper(); SyncScenario thread1 = new SyncScenario("java", inc1); SyncScenario thread2 = new SyncScenario("sql", inc1); } } class SyncScenario implements Runnable{ String name; IncrementOper inc; Thread t; SyncScenario(String name, IncrementOper inc){ this.name=name; this.inc=inc; t =new Thread(this,name); t.start(); } public void run() { System.out.println("Thread started: "+t.getName()); synchronized(inc){ inc.noSynMethod(name); } System.out.println("Thread ended: "+t.getName()); } } class IncrementOper { public synchronized void incMethod(String name){ for(int i=0;i<5;i++){ System.out.println("Running Thread name:"+name+" count"+i); } } public void noSynMethod(String name){ for(int i=0;i<5;i++){ incMethod(name); System.out.println("Running No Sync:"+name+" count"+i); } } }