Java Multithreading
There are two types of threads in an application – user thread and daemon thread. When we start an application, main is the first user thread created and we can create multiple user threads as well as daemon threads. When all the user threads are executed, JVM terminates the program.We can create Threads by either implementing Runnable interface or by extending Thread Class.
Point to remember -:
Java Thread Sleep
There are two types of threads in an application – user thread and daemon thread. When we start an application, main is the first user thread created and we can create multiple user threads as well as daemon threads. When all the user threads are executed, JVM terminates the program.We can create Threads by either implementing Runnable interface or by extending Thread Class.
Thread t = new Thread(new Runnable(){ @Override public void run() { } });Thread Life cycle
Point to remember -:
- Syntax of Thread class: public class Thread extends Object implements Runnable
- Method of Runnable interface: void run()
1
|
Thread.sleep();
|
Java Thread Sleep important points:
- It always pause the current thread execution.
- The actual time thread sleeps before waking up and start execution depends on system timers and schedulers. For a quiet system, the actual time for sleep is near to the specified sleep time but for a busy system it will be little bit more.
- Thread sleep doesn’t lose any monitors or locks current thread has acquired.
- Any other thread can interrupt the current thread in sleep, in that case InterruptedException is thrown.
- Sleep is a static method of Thread class.
Java Thread yield
Currently running thread goes back to its runnable state (so it’s ready to run again, but is currently not running), so other threads have a chance to run. It’s only a hint for the thread scheduler (it can be ignored), so the given behavior (goin back to runnable state) is not guaranteed.
Java Thread Join
Java Thread join method can be used to pause the current thread execution until unless the specified thread is dead.public final void join(): This java thread join method puts the current thread on wait until the thread on which it’s called is dead. If the thread is interrupted, it throws InterruptedException.public class ThreadJoinExample { public static void main(String[] args) { Thread t1 = new Thread(new MyRunnable(), "t1"); Thread t2 = new Thread(new MyRunnable(), "t2"); Thread t3 = new Thread(new MyRunnable(), "t3"); t1.start(); //start second thread after waiting for 2 seconds or if it's dead try { t1.join(2000); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); //start third thread only when first thread is dead try { t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } t3.start(); //let all threads finish execution before finishing main thread try { t1.join(); t2.join(); t3.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("All threads are dead, exiting main thread"); } } class MyRunnable implements Runnable{ @Override public void run() { System.out.println("Thread started:::"+Thread.currentThread().getName()); try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread ended:::"+Thread.currentThread().getName()); } }
Output of the above program is:
Thread started:::t1 Thread started:::t2 Thread ended:::t1 Thread started:::t3 Thread ended:::t2 Thread ended:::t3 All threads are dead, exiting main thread
Java Thread wait, notify, notifyAll
Key Points -:
As I suggested, you should always invoke wait method from a loop. The loop is used to test the condition before and after waiting. If the condition still holds and the notify (or notifyAll) method has already been invoked before a thread calls wait() method, then there is no guarantee that the thread will ever awake from the wait, potentially causing a deadlock.
Synchronization
Synchronization in Java is an important concept since Java is a multi-threaded language where multiple threads run in parallel to complete program execution. In multi-threaded environment synchronization of Java object or synchronization of Java class becomes extremely important. Synchronization in Java is possible by using Java keywords "synchronized" and "volatile”. Inter-thread communication or Co-operation is all about allowing synchronized threads to communicate with each other.Cooperation (Inter-thread communication) is a mechanism in which a thread is paused running in its critical section and another thread is allowed to enter (or lock) in the same critical section to be executed.It is implemented by following methods of Object class:
- wait()
- notify()
- notifyAll()
Example: Producer Consumer Problemwait
Object wait methods has three variance, one which waits indefinitely for any other thread to call notify or notifyAll method on the object to wake up the current thread. Other two variances puts the current thread in wait for specific amount of time before they wake up.notify
notify method wakes up only one thread waiting on the object and that thread starts execution. So if there are multiple threads waiting for an object, this method will wake up only one of them. The choice of the thread to wake depends on the OS implementation of thread management.notifyAll
notifyAll method wakes up all the threads waiting on the object, although which one will process first depends on the OS implementation.ExampleOutput: going to withdraw... Less balance; waiting for deposit... going to deposit... deposit completed... withdraw completed
Key Points -:
- You need to call wait() method on the object which is shared between two threads, in producer-consumer problem its the queue which is shared between producer and consumer threads.
- The second confusion comes from the fact that wait needs to be a call from synchronized block or method? So if you use synchronized block, which object should be put to go inside the block? This should be the same object, whose lock you want to acquire i.e. the shared object between multiple threads. In our case it's queue.
- Once you know that you need to call wait from synchronized context and on the shared object, next thing is to avoid mistake made by several Java developer by calling wait()method inside if block instead of while loop.
Based upon above knowledge here is the standard code template or idiom to call wait and notify method in Java :
// The standard idiom for calling the wait method in Java synchronized (sharedObject) { while (condition) { sharedObject.wait(); // (Releases lock, and reacquires on wakeup) } ... // do action based upon condition e.g. take or put into queue }
As I suggested, you should always invoke wait method from a loop. The loop is used to test the condition before and after waiting. If the condition still holds and the notify (or notifyAll) method has already been invoked before a thread calls wait() method, then there is no guarantee that the thread will ever awake from the wait, potentially causing a deadlock.
Things to Remember about Using wait(), notify() and notifyAll() method
- You can use wait() and notify() method to implement inter-thread communication in Java. Not just one or two threads but multiple threads can communicate to each other by using these methods.
- Always call wait(), notify() and notifyAll() methods from synchronized method or synchronized block otherwise JVM will throw IllegalMonitorStateException.
- Always call wait and notify method from a loop and never from if() block, because loop test waiting condition before and after sleeping and handles notification even if waiting for the condition is not changed.
- Always call wait in shared object e.g. shared queue in this example.
- Prefer notifyAll() over notify() method due to reasons given in this article.
Producer Consumer problem:
Synchronization
Concurrent access of shared objects in Java introduces to kind of errors: thread interference and memory consistency errors and to avoid these errors you need to properly synchronize your Java object to allow mutual exclusive access of critical section to two threads.
- Java synchronization works on locking and unlocking of resource, before any thread enters into synchronized code, it has to acquire lock on the Object and when code execution ends, it unlocks the resource that can be locked by other threads. In the mean time other threads are in wait state to lock the synchronized resource.
- We can use synchronized keyword in two ways, one is to make a complete method synchronized and other way is to create synchronized block.
- When a method is synchronized, it locks the Object, if method is static it locks the Class, so it's always best practice to use synchronized block to lock the only sections of method that needs synchronization.
- While creating synchronized block, we need to provide the resource on which lock will be acquired, it can be XYZ.class or any Object field of the class.
- synchronized(this) will lock the Object before entering into the synchronized block.
- You should use the lowest level of locking, for example if there are multiple synchronized block in a class and one of them is locking the Object, then other synchronized blocks will also be not available for execution by other threads. When we lock an Object, it acquires lock on all the fields of the Object.
- Java Synchronization provides data integrity on the cost of performance, so it should be used only when it's absolutely necessary.
Volatile
Reflection
Java Reflection is a process of examining or modifying the run time behavior of a class at run time.
The java.lang.Class class provides many methods that can be used to get metadata, examine and change the run time behavior of a class.
The java.lang and java.lang.reflect packages provide classes for java reflection.
There are 3 ways to get the instance of Class class. They are as follows:
- forName() method of Class class
- getClass() method of Object class
- the .class syntax
Typical ways Of Object creation
- Using new operator - new xyzClass()
- Using factory methods - xyzFactory.getInstance( )
- Using newInstance( ) method - (Class.forName(xyzClassÂ))emp.newInstance( )
- By cloning an already available object - (xyzClass)obj1.clone( )
Fail Fast Vs Fail Safe Iterators In Java :
Fail-Fast Iterators | Fail-Safe Iterators |
Fail-Fast iterators doesn’t allow modifications of a collection while iterating over it. | Fail-Safe iterators allow modifications of a collection while iterating over it. |
These iterators throw ConcurrentModificationException if a collection is modified while iterating over it. | These iterators don’t throw any exceptions if a collection is modified while iterating over it. |
They use original collection to traverse over the elements of the collection. | They use copy of the original collection to traverse over the elements of the collection. |
These iterators don’t require extra memory. | These iterators require extra memory to clone the collection. |
Ex : Iterators returned by ArrayList, Vector, HashMap. | Ex : Iterator returned by ConcurrentHashMap. |
What is Shallow Copy?
Shallow copy is a bit-wise copy of an object. A new object is created that has an exact copy of the values in the original object. If any of the fields of the object are references to other objects, just the reference addresses are copied i.e., only the memory address is copied.
In this figure, the MainObject1 have fields "field1" of int type, and "ContainObject1" of ContainObject type. When you do a shallow copy of MainObject1, MainObject2 is created with "field2" containing the copied value of "field1" and still pointing to ContainObject1 itself. Observe here and you will find that since field1 is of primitive type, the values of it are copied to field3 but ContainedObject1 is an object, so MainObject2 is still pointing to ContainObject1. So any changes made to ContainObject1 in MainObject1 will reflect in MainObject2.
Now if this is shallow copy, lets see what's deep copy?
What is Deep Copy?
A deep copy copies all fields, and makes copies of dynamically allocated memory pointed to by the fields. A deep copy occurs when an object is copied along with the objects to which it refers.
In this figure, the MainObject1 have fields "field1" of int type, and "ContainObject1" of ContainObject type. When you do a deep copy of MainObject1, MainObject2 is created with "field3" containing the copied value of "field1" and "ContainObject2" containing the copied value of ContainObject1.So any changes made to ContainObject1 in MainObject1 will not reflect in MainObject2.
Well, here we are with what shallow copy and deep copy are and obviously the difference between them. Now lets see how to implement them in java.
How to implement shallow copy in java?
Here is an example of Shallow Copy implementation
class Subject { private String name; public String getName() { return name; } public void setName(String s) { name = s; } public Subject(String s) { name = s; } } class Student implements Cloneable { //Contained object private Subject subj; private String name; public Subject getSubj() { return subj; } public String getName() { return name; } public void setName(String s) { name = s; } public Student(String s, String sub) { name = s; subj = new Subject(sub); } public Object clone() { //shallow copy try { return super.clone(); } catch (CloneNotSupportedException e) { return null; } } } public class CopyTest { public static void main(String[] args) { //Original Object Student stud = new Student("John", "Algebra"); System.out.println("Original Object: " + stud.getName() + " - " + stud.getSubj().getName()); //Clone Object Student clonedStud = (Student) stud.clone(); System.out.println("Cloned Object: " + clonedStud.getName() + " - " + clonedStud.getSubj().getName()); stud.setName("Dan"); stud.getSubj().setName("Physics"); System.out.println("Original Object after it is updated: " + stud.getName() + " - " + stud.getSubj().getName()); System.out.println("Cloned Object after updating original object: " + clonedStud.getName() + " - " + clonedStud.getSubj().getName()); } } Output is: Original Object: John - Algebra Cloned Object: John - Algebra Original Object after it is updated: Dan - Physics Cloned Object after updating original object: John - Physics
In this example, all I did is, implement the class that you want to copy with Clonable interface and override clone() method of Object class and call super.clone() in it. If you observe, the changes made to "name" field of original object (Student class) is not reflected in cloned object but the changes made to "name" field of contained object (Subject class) is reflected in cloned object. This is because the cloned object carries the memory address of the Subject object but not the actual values. Hence any updates on the Subject object in Original object will reflect in Cloned object.
How to implement deep copy in java?
Here is an example of Deep Copy implementation. This is the same example of Shallow Copy implementation and hence I didnt write the Subject and CopyTest classes as there is no change in them.
class Student implements Cloneable { //Contained object private Subject subj; private String name; public Subject getSubj() { return subj; } public String getName() { return name; } public void setName(String s) { name = s; } public Student(String s, String sub) { name = s; subj = new Subject(sub); } public Object clone() { //Deep copy Student s = new Student(name, subj.getName()); return s; } } Output is: Original Object: John - Algebra Cloned Object: John - Algebra Original Object after it is updated: Dan - Physics Cloned Object after updating original object: John - Algebra
Another Explanation
Shallow Copy
Generally clone method of an object, creates a new instance of the same class and copies all the fields to the new instance and returns it. This is nothing but shallow copy. Object class provides a clone method and provides support for the shallow copy. It returns ‘Object’ as type and you need to explicitly cast back to your original object.
Since the Object class has the clone method (protected) you cannot use it in all your classes. The class which you want to be cloned should implement clone method and overwrite it. It should provide its own meaning for copy or to the least it should invoke the super.clone(). Also you have to implement Cloneable marker interface or else you will get CloneNotSupportedException. When you invoke the super.clone() then you are dependent on the Object class’s implementation and what you get is a shallow copy.
Deep Copy
When you need a deep copy then you need to implement it yourself. When the copied object contains some other object its references are copied recursively in deep copy. When you implement deep copy be careful as you might fall for cyclic dependencies. If you don’t want to implement deep copy yourselves then you can go for serialization. It does implements deep copy implicitly and gracefully handling cyclic dependencies
Lazy Copy
A lazy copy is a combination of both shallow copy and deep copy. When initially copying an object, a (fast) shallow copy is used. A counter is also used to track how many objects share the data. When the program wants to modify the original object, it can determine if the data is shared (by examining the counter) and can do a deep copy at that time if necessary.Garbage Collector
Garbage collection is an automatic process in Java which relieves the programmer of object memory allocation and de-allocation chores.
Java has four types of garbage collectors,
- Serial Garbage Collector
- Parallel Garbage Collector
- CMS Garbage Collector
- G1 Garbage Collector
1. Serial Garbage Collector
Serial garbage collector works by holding all the application threads. It is designed for the single-threaded environments. It uses just a single thread for garbage collection. The way it works by freezing all the application threads while doing garbage collection may not be suitable for a server environment. It is best suited for simple command-line programs.
Turn on the
-XX:+UseSerialGC
JVM argument to use the serial garbage collector.2. Parallel Garbage Collector
Parallel garbage collector is also called as throughput collector. It is the default garbage collector of the JVM. Unlike serial garbage collector, this uses multiple threads for garbage collection. Similar to serial garbage collector this also freezes all the application threads while performing garbage collection.
3. CMS Garbage Collector
Concurrent Mark Sweep (CMS) garbage collector uses multiple threads to scan the heap memory to mark instances for eviction and then sweep the marked instances. CMS garbage collector holds all the application threads in the following two scenarios only,
- while marking the referenced objects in the tenured generation space.
- if there is a change in heap memory in parallel while doing the garbage collection.
In comparison with parallel garbage collector, CMS collector uses more CPU to ensure better application throughput. If we can allocate more CPU for better performance then CMS garbage collector is the preferred choice over the parallel collector.
Turn on the
XX:+USeParNewGC
JVM argument to use the CMS garbage collector.4. G1 Garbage Collector
G1 garbage collector is used for large heap memory areas. It separates the heap memory into regions and does collection within them in parallel. G1 also does compacts the free heap space on the go just after reclaiming the memory. But CMS garbage collector compacts the memory on stop the world (STW) situations. G1 collector prioritizes the region based on most garbage first.
Turn on the
–XX:+UseG1GC
JVM argument to use the G1 garbage collector.Garbage Collection JVM Options
Following are the key JVM options that are related to Java garbage collection.
Type of Garbage Collector to run
Option | Description |
---|---|
-XX:+UseSerialGC | Serial Garbage Collector |
-XX:+UseParallelGC | Parallel Garbage Collector |
-XX:+UseConcMarkSweepGC | CMS Garbage Collector |
-XX:ParallelCMSThreads= | CMS Collector – number of threads to use |
-XX:+UseG1GC | G1 Gargbage Collector |
Important Points of Garbage Collector
1) Objects are created on the heap in Java irrespective of their scope e.g. local or member variable. while it's worth noting that class variables or static members are created in method area of Java memory space and both heap and method area is shared between different thread.
2) Garbage collection is a mechanism provided by Java Virtual Machine to reclaim heap space from objects which are eligible for Garbage collection.
3) Garbage collection relieves Java programmer from memory management which is an essential part of C++ programming and gives more time to focus on business logic.
4) Garbage Collection in Java is carried by a daemon thread called Garbage Collector.
5) Before removing an object from memory garbage collection thread invokes finalize()method of that object and gives an opportunity to perform any sort of cleanup required.
6) You as Java programmer can not force garbage collection in Java; it will only trigger if JVM thinks it needs a garbage collection based on Java heap size.
7) There are methods like System.gc() and Runtime.gc() which is used to send request of Garbage collection to JVM but it’s not guaranteed that garbage collection will happen.
8) If there is no memory space for creating a new object in Heap Java Virtual Machine throws OutOfMemoryError or java.lang.OutOfMemoryError heap space
9) J2SE 5(Java 2 Standard Edition) adds a new feature called Ergonomics goal of ergonomics is to provide good performance from the JVM with a minimum of command line tuning. See Java Performance The Definitive Guide for more details on garbage collection tuning.
2) Garbage collection is a mechanism provided by Java Virtual Machine to reclaim heap space from objects which are eligible for Garbage collection.
3) Garbage collection relieves Java programmer from memory management which is an essential part of C++ programming and gives more time to focus on business logic.
4) Garbage Collection in Java is carried by a daemon thread called Garbage Collector.
5) Before removing an object from memory garbage collection thread invokes finalize()method of that object and gives an opportunity to perform any sort of cleanup required.
6) You as Java programmer can not force garbage collection in Java; it will only trigger if JVM thinks it needs a garbage collection based on Java heap size.
7) There are methods like System.gc() and Runtime.gc() which is used to send request of Garbage collection to JVM but it’s not guaranteed that garbage collection will happen.
8) If there is no memory space for creating a new object in Heap Java Virtual Machine throws OutOfMemoryError or java.lang.OutOfMemoryError heap space
9) J2SE 5(Java 2 Standard Edition) adds a new feature called Ergonomics goal of ergonomics is to provide good performance from the JVM with a minimum of command line tuning. See Java Performance The Definitive Guide for more details on garbage collection tuning.
http://javapapers.com/java/types-of-java-garbage-collectors/
Brilliant blog I visit this blog it's incredibly awesome. Curiously, in this blog content formed doubtlessly and sensible. The substance of information is helpful.
ReplyDeleteWorkday Online Training