What are different ways in which a thread can enter the waiting state?
A thread can enter the waiting state by the following ways:
- Invoking its sleep() method,
- By blocking on I/O
- By unsuccessfully attempting to acquire an object's lock
- By invoking an object's wait() method.
- It can also enter the waiting state by invoking its (deprecated) suspend() method.
What is difference between thread and process?
A thread is a class in java that belongs to java.lang package. A thread is an lightweight process and has its own call stack. In Java, you can run multiple threads parallely. A thread is used to perform long running jobs dedicated without disturbing to the other part of program. Even if you don't create any new threads in your program, there is at least one thread i.e. main thread() which runs the application.
- Threads share the address space of the process that created it; processes have their own address.
- Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.
- Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
- Threads have almost no overhead; processes have considerable overhead.
- New threads are easily created; new processes require duplication of the parent process.
- Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
- Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process do not affect child processes.
What are the different ways to create threads in Java?
We can define and implement a thread in java using two ways: Extending the Thread class
class ThreadExample extends Thread { public void run(){ System.out.println("Thread runs..."); } public static void main(String args[]){ ThreadExample ib = new ThreadExample(); ib.start(); } }
Implementing the Runnable interface
class ThreadExample implements Runnable { public void run(){ System.out.println("Thread runs..."); } public static void main(String args[]){ Thread ib = new Thread(new ThreadExample()); ib.start(); } }
Implementing a thread using the method of Runnable interface is more preferred and advantageous as Java does not have support for multiple inheritances of classes. start() method is used for creating a separate call stack for the thread execution. Once the call stack is created, JVM calls the run() method for executing the thread in that call stack.
What are the differences between HashMap and HashTable in Java?
HashMap | HashTable |
---|---|
HashMap is not synchronized thereby making it better for non-threaded applications. | HashTable is synchronized and hence it is suitable for threaded applications. |
Allows only one null key but any number of null in the values. | This does not allow null in both keys or values. |
Supports order of insertion by making use of its subclass LinkedHashMap. | Order of insertion is not guaranteed in HashTable. |
What makes a HashSet different from a TreeSet?
Although both HashSet and TreeSet are not synchronized and ensure that duplicates are not present, there are certain properties that distinguish a HashSet from a TreeSet.
Implementation: For a HashSet, the hash table is utilized for storing the elements in an unordered manner. However, TreeSet makes use of the red-black tree to store the elements in a sorted manner.
Complexity/ Performance: For adding, retrieving, and deleting elements, the time amortized complexity is O(1) for a HashSet. The time complexity for performing the same operations is a bit higher for TreeSet and is equal to O(log n). Overall, the performance of HashSet is faster in comparison to TreeSet.
Methods: hashCode() and equals() are the methods utilized by HashSet for making comparisons between the objects. Conversely, compareTo() and compare() methods are utilized by TreeSet to facilitate object comparisons.
Objects type: Heterogeneous and null objects can be stored with the help of HashSet. In the case of a TreeSet, runtime exception occurs while inserting heterogeneous objects or null objects.
What is a Comparator in java?
Consider the example where we have an ArrayList of employees like( EId, Ename, Salary), etc. Now if we want to sort this list of employees based on the names of employees. Then that is not possible to sort using the Collections.sort() method. We need to provide something to the sort() function depending on what values we have to perform sorting. Then in that case a comparator is used.
Comparator is the interface in java that contains the compare method. And by overloading the compare method, we can define that on what basis we need to compare the values.
How would you differentiate between a String, StringBuffer, and a StringBuilder?
Storage area: In string, the String pool serves as the storage area. For StringBuilder and StringBuffer, heap memory is the storage area.
Mutability: A String is immutable, whereas both the StringBuilder and StringBuffer are mutable.
Efficiency: It is quite slow to work with a String. However, StringBuilder is the fastest in performing operations. The speed of a StringBuffer is more than a String and less than a StringBuilder. (For example appending a character is fastest in StringBuilder and very slow in String because a new memory is required for the new String with appended character.)
Thread-safty: In the case of a threaded environment, StringBuilder and StringBuffer are used whereas a String is not used. However, StringBuilder is suitable for an environment with a single thread, and a StringBuffer is suitable for multiple threads.
Syntax:
// String String first = "InterviewBit"; String second = new String("InterviewBit"); // StringBuffer StringBuffer third = new StringBuffer("InterviewBit"); // StringBuilder StringBuilder fourth = new StringBuilder("InterviewBit");
Why is the main method static in Java?
The main method is always static because static members are those methods that belong to the classes, not to an individual object. So if the main method will not be static then for every object, It is available. And that is not acceptable by JVM. JVM calls the main method based on the class name itself. Not by creating the object.
Because there must be only 1 main method in the java program as the execution starts from the main method. So for this reason the main method is static.
How is an infinite loop declared in Java?
Infinite loops are those loops that run infinitely without any breaking conditions. Some examples of consciously declaring infinite loop is:
Using For Loop:for (;;) { // Business logic // Any break logic }Using while loop:
while(true){ // Business logic // Any break logic }Using do-while loop:
do{ // Business logic // Any break logic } while(true);
What?s the difference between comparison done by equals method and == operator?
In Java, equals() method is used to compare the contents of two string objects and returns true if the two have same value while == operator compares the references of two string objects.
In the following example, equals() returns true as the two string objects have same values. However == operator returns false as both string objects are referencing to different objects:
public class EqualsTest { public static void main(String args[]) { String str1 = new String("Hello World"); String str2 = new String("Hello World"); //Reference comparison System.out.println(s1 == s2); //Content comparison System.out.println(s1.equals(s2)); // integer-type System.out.println(10 == 10); // char-type System.out.println('a' == 'a'); } }
Output
false true true true
What are the different states of a thread's life cycle?
- New - When a thread is instantiated it is in New state until the start() method is called on the thread instance. In this state the thread is not considered to be alive.
- Runnable - The thread enters into this state after the start method is called in the thread instance. The thread may enter into the Runnable state from Running state. In this state the thread is considered to be alive.
- Running - When the thread scheduler picks up the thread from the Runnable thread's pool, the thread starts running and the thread is said to be in Running state.
- Waiting/Blocked/Sleeping - In these states the thread is said to be alive but not runnable. The thread switches to this state because of reasons like wait method called or sleep method has been called on the running thread or thread might be waiting for some i/o resource so blocked. Dead - When the thread finishes its execution i.e. the run() method execution completes, it is said to be in dead state. A dead state can not be started again. If a start() method is invoked on a dead thread a runtime exception will occur.
What is the difference between yield and sleep?
When a task invokes its yield() method, it returns to the ready state, either from waiting, running or after its creation. When a task invokes its sleep() method, it returns to the waiting state from a running state.
Extending Thread class or implementing Runnable Interface. Which is better?
You have two ways to create a thread in Java. First, making your class "extends" Thread class. The other way is making your class implement "Runnable" interface.
The latter is more advantageous, cause when you are going for multiple inheritance, then only interface can help. If you are already inheriting a different class, then you have to go for Runnable Interface. Also, if you are implementing interface, it means you have to implement all methods in the interface.
Both Thread class and Runnable interface are provided for convenience and use them as per the requirement. But if you are not extending any class, better extend Thread class as it will save few lines of coding. Otherwise performance wise, there is no distinguishable difference. A thread is in the ready state after it has been created and started.
What is Mutual Exclusion (Mutex)? How to Handle Mutex in Java?
Mutual exclusion in Java is a mechanism that allows only one thread to access a shared resource or critical section of code at a time, preventing race conditions where multiple threads can access and modify the same resource simultaneously.
For mutual exclusion, you can simply use the synchronized
keyword, which can be applied to a method or a block of code to ensure that only one thread can access the synchronized code at a time.
Java offers different options to achieve mutual exclusion, such as the Semaphore
class, the ReadWriteLock
interface, the AtomicInteger
class, and the StampedLock
class. The choice of implementation depends on the specific requirements and constraints of the application.
- Semaphore: The Semaphore class can be used to implement mutual exclusion. It allows a limited number of threads to access a critical section at the same time.
- ReadWriteLock: The ReadWriteLock interface can be used to implement mutual exclusion for read and write operations. It allows multiple threads to read a shared resource simultaneously, but only one thread can write to the resource at a time.
- AtomicInteger: The AtomicInteger class can be used to implement mutual exclusion for integer values. It provides atomic operations such as incrementAndGet() and decrementAndGet(), which ensures that only one thread can modify the value at a time.
- StampedLock: The StampedLock class can be used to implement mutual exclusion for read and write operations. It provides optimistic read locks, which allow multiple threads to read a shared resource simultaneously, and a write lock, which allows only one thread to write to the resource at a time.
What is the difference between preemptive scheduling and time slicing?
Under preemptive scheduling, the highest priority task executes until it enters the waiting or dead states or a higher priority task comes into existence. Under time slicing, a task executes for a predefined slice of time and then re-enters the pool of ready tasks. The scheduler then determines which task should execute next, based on priority and other factors.
What is deadlock?
When two threads are waiting for each other and can't proceed until the first thread obtains a lock on the other thread or vice versa, the program is said to be in a deadlock.
What are synchronized methods and synchronized statements?
Synchronized methods are methods that are used to control access to an object. A thread only executes a synchronized method after it has acquired the lock for the method's object or class. Synchronized statements are similar to synchronized methods. A synchronized statement can only be executed after a thread has acquired the lock for the object or class referenced in the synchronized statement.
What is a volatile keyword?
In general, each thread has its own copy of the variable, such that one thread is not concerned with the value of the same variable in the other thread. But sometime this may not be the case. Consider a scenario in which the count variable is holding the number of times a method is called for a given class irrespective of any thread calling, in this case, irrespective of thread access the count has to be increased so the count variable is declared as volatile.
The copy of the volatile variable is stored in the main memory, so every time a thread access the variable even for reading purpose the local copy is updated each time from the main memory. The volatile variable also has performance issues.
What is Serializable?
Serializable is a marker interface. When an object has to be transferred over a network ( typically through RMI or EJB) or persists the state of an object to a file, the object Class needs to implement a Serializable interface. Implementing this interface will allow the object converted into a byte stream and transfer over a network.
What is use of serialVersionUID?
During object serialization, the default Java serialization mechanism writes the metadata about the object, which includes the class name, field names, types, and superclass. This class definition is stored as a part of the serialized object. This stored metadata enables the deserialization process to reconstitute the objects and map the stream data into the class attributes with the appropriate type every time an object is serialized the java serialization mechanism automatically computes a hash value.
ObjectStreamClass’s computeSerialVersionUID() method passes the class name, sorted member names, modifiers, and interfaces to the secure hash algorithm (SHA), which returns a hash value. The serialVersionUID is also called suid.
So when the serialized object is retrieved, the JVM first evaluates the suid of the serialized class and compares the suid value with the one of the objects. If the suid values match then the object is said to be compatible with the class and hence it is de-serialized. If not InvalidClassException exception is thrown.
Changes to a serializable class can be compatible or incompatible.