1. What is String in Java?
String is a Class in java and defined in java.lang package. It’s not a primitive data type like int and long. String class represents character Strings. String is used in almost all the Java applications and there are some interesting facts we should know about String. String in immutable and final in Java and JVM uses String Pool to store all the String objects.
Some other interesting things about String is the way we can instantiate a String object using double quotes and overloading of “+” operator for concatenation.
2. Difference between String, StringBuilder, and StringBuffer?
The string is immutable and final in Java, so whenever we do String manipulation, it creates a new String. String manipulations are resource consuming, so java provides two utility classes for String manipulations – StringBuffer and StringBuilder.
StringBuffer and StringBuilder are mutable classes. StringBuffer operations are thread-safe and synchronized where StringBuilder operations are not thread-safe. So in a multi-threaded environment, we should use StringBuffer but in the single-threaded environment, we should use StringBuilder.
StringBuilder performance is fast than StringBuffer because of no overhead of synchronization.
3. Why is String immutable or final?
There are several benefits of String because it’s immutable and final.
4. What is a String pool?
As the name suggests, String Pool is a pool of Strings stored in Java heap memory. We know that String is a special class in Java and we can create String objects using the new operator as well as providing values in double-quotes.
Check this post for more details about String Pool.
5. How to reverse a String?
public static void main(String[] args) { System.out.println("Enter string to reverse:"); Scanner read = new Scanner(System.in); String str = read.nextLine(); StringBuilder sb = new StringBuilder(); for(int i = str.length() - 1; i >= 0; i--) { sb.append(str.charAt(i)); } System.out.println("Reversed string is:"); System.out.println(sb.toString()); }
Use StringBuilder reverse() method.
public static void main(String[] args) { System.out.println("Enter string to reverse:"); Scanner read = new Scanner(System.in); String str = read.nextLine(); StringBuilder sb = new StringBuilder(str); System.out.println("Reversed string is:"); System.out.println(sb.reverse().toString()); }
6. Why String is a popular HashMap key?
Since String is immutable, its hashcode is cached at the time of creation and it doesn’t need to be calculated again. This makes it a great candidate for the key in a Map and it’s processing is fast than other HashMap key objects. This is why String is mostly used Object as HashMap keys.
7. What are the different ways to create a string?
String str = new String("folau");// by using the new keyword String str1 = "folau";// by using the double quotes
8. Check for palindrome (string is equal to its reversed version)
private static boolean isPalindromeString(String str) { if (str == null) return false; int length = str.length(); System.out.println(length / 2); for (int i = 0; i < length / 2; i++) { if (str.charAt(i) != str.charAt(length - i - 1)) return false; } return true; }
Use StringBuilder reverse() method.
private static boolean isPalindrome(String str) { if (str == null) return false; StringBuilder strBuilder = new StringBuilder(str); strBuilder.reverse(); return strBuilder.toString().equals(str); }
9. Remove a single character from a string
Use the Character class to create a string and pass it to the replaceAll method.
private static String removeChar(String str, char c) { if (str == null) return null; return str.replaceAll(Character.toString(c), ""); }
10. Convert String to char and vice versa?
We can’t convert a string to a char because a char is a single character. On the other hand, we can use charAt or toCharArray to convert chars to a string.
11. Find all permutations of a string
public static Set<String> permutationFinder(String str) { Set<String> perm = new HashSet<String>(); //Handling error scenarios if (str == null) { return null; } else if (str.length() == 0) { perm.add(""); return perm; } char initial = str.charAt(0); // first character String rem = str.substring(1); // Full string without first character Set<String> words = permutationFinder(rem); for (String strNew : words) { for (int i = 0;i<=strNew.length();i++){ perm.add(charInsert(strNew, initial, i)); } } return perm; } public static String charInsert(String str, char c, int j) { String begin = str.substring(0, j); String end = str.substring(j); return begin + c + end; } public static void main(String[] args) { String s = "AAC"; String s1 = "ABC"; String s2 = "ABCD"; System.out.println("\nPermutations for " + s + " are: \n" + permutationFinder(s)); System.out.println("\nPermutations for " + s1 + " are: \n" + permutationFinder(s1)); System.out.println("\nPermutations for " + s2 + " are: \n" + permutationFinder(s2)); }
11. Find the longest palindrome in a string.
public static void main(String[] args) { System.out.println(longestPalindromeString("1234")); System.out.println(longestPalindromeString("12321")); System.out.println(longestPalindromeString("9912321456")); System.out.println(longestPalindromeString("9912333321456")); System.out.println(longestPalindromeString("12145445499")); System.out.println(longestPalindromeString("1223213")); System.out.println(longestPalindromeString("abb")); } static public String intermediatePalindrome(String s, int left, int right) { if (left > right) return null; while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { left--; right++; } return s.substring(left + 1, right); } // O(n^2) public static String longestPalindromeString(String s) { if (s == null) return null; String longest = s.substring(0, 1); for (int i = 0; i < s.length() - 1; i++) { //odd cases like 121 String palindrome = intermediatePalindrome(s, i, i); if (palindrome.length() > longest.length()) { longest = palindrome; } //even cases like 1221 palindrome = intermediatePalindrome(s, i, i + 1); if (palindrome.length() > longest.length()) { longest = palindrome; } } return longest; }
12. Why char array is preferred over string for database password?
String is immutable in Java and stored in String pool. Once it’s created it stays in the pool until unless garbage collected, so even though we are done with password it’s available in memory for longer duration and there is no way to avoid it. It’s a security risk because anyone having access to memory dump can find the password as clear text.
If we use a char array to store password, we can set it to blank once we are done with it. So we can control for how long it’s available in memory that avoids the security threat with String.
13. Check if two strings are the same?
String s1 = "abc"; String s2 = "abc"; String s3= new String("abc"); System.out.println("s1 == s2 ? "+(s1==s2)); //true System.out.println("s1 == s3 ? "+(s1==s3)); //false System.out.println("s1 equals s3 ? "+(s1.equals(s3))); //true
There are two ways to check if two Strings are equal or not – using “==” operator or using equals
method. When we use “==” operator, it checks for the value of String as well as the reference but in our programming, most of the time we are checking equality of String for value only. So we should use the equals method to check if two Strings are equal or not.
There is another function equalsIgnoreCase
that we can use to ignore case.
13. is String thread-safe?
Strings are immutable, so we can’t change its value in runtime. Hence it’s thread-safe and can be safely used in a multi-threaded environment.
December 16, 20191. What is Serialization?
Serialization is the process of converting an object and its states to a binary stream that can then be saved into a database, cached or sent over the network to another JVM.
2. What is Deserialization?
Deserialization is the process of converting back a serialized object.
import java.io.Serializable; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; public class User implements Serializable { private static final long serialVersionUID = 3L; private String name; private int age; private String email; transient private double height; //setters and getters @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } }
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializationDemo { public static void main(String[] args) throws IOException, ClassNotFoundException { String path = "serialized_user.ser"; User serializedUser = serialize(path); System.out.println("serializedUser=" + serializedUser.toString()); User deserializedUser = deserialize(path); System.out.println("deserializedUser=" + deserializedUser.toString()); } private static User serialize(String path) throws IOException { FileOutputStream fileStream = new FileOutputStream(path); ObjectOutputStream objectStream = new ObjectOutputStream(fileStream); User user = new User(); user.setAge(21); user.setName("Laulau"); user.setEmail("folaukaveinga@gmail.com"); user.setHeight(6.3); objectStream.writeObject(user); objectStream.close(); fileStream.close(); return user; } private static User deserialize(String path) throws IOException, ClassNotFoundException { FileInputStream fileInputStream = new FileInputStream(path); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); User user = (User) objectInputStream.readObject(); objectInputStream.close(); fileInputStream.close(); return user; } }
Result
serializedUser=User[name=Laulau,age=21,email=folaukaveinga@gmail.com] deserializedUser=User[name=Laulau,age=21,email=folaukaveinga@gmail.com]
3. What is Externalization?
Serialization is not very efficient. If you serialize bloated objects having a lot of attributes and properties, you do not wish to serialize. This is where Externalization in Java comes into the picture. Externalization is an advanced way of serialization. It is whenever you need to customize the serialization mechanism.
The class you want to be externalized must implement the Externalizable interface, then serialization of the object will be done using the method writeExternal(). When the Externalizable object is reconstructed at the receiver’s end, an instance will be created using no-argument constructor and this method is called readExternal().
This basically serves the purpose of custom Serialization, where you can decide what to store in a stream.
When to use Externalization?
When you want or need to serialize only part of an object, Externalization is the best option.
How to use Externalization?
By implementing the Externalizable interface, you control the process of reading and writing the objects during serialization and de-serialization process, you need to have the object’s class implemented the interface java.io.Externalizable. Only then you can implement your own code to read and write the object’s states. The methods, readExternal() and writeExternal() are defined by the Externalizable interface.
import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; public class Member implements Externalizable { public static final long serialVersionUID = 2L; private String name; private int age; private String email; transient private double height; // setters and getters @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println("writing object state..."); // TODO Auto-generated method stub out.writeObject(name); out.writeObject(email); out.writeInt(age); out.writeDouble(height); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("reading object state..."); this.name = (String) in.readObject(); this.email = (String) in.readObject(); this.age = in.readInt(); this.height = in.readDouble(); } }
public class ExternalizeDemo { public static void main(String[] args) throws IOException, ClassNotFoundException { String path = "externalized_member.ser"; Member externalizedMember = serialize(path); System.out.println("externalizedMember=" + externalizedMember.toString()); Member dexternalizedMember = deserialize(path); System.out.println("dexternalizedMember=" + dexternalizedMember.toString()); } private static Member serialize(String path) throws IOException { FileOutputStream fileStream = new FileOutputStream(path); ObjectOutputStream objectStream = new ObjectOutputStream(fileStream); Member member = new Member(); member.setAge(21); member.setName("Laulau"); member.setEmail("folaukaveinga@gmail.com"); member.setHeight(6.3); System.out.println(member.toString()); objectStream.writeObject(member); objectStream.close(); fileStream.close(); return member; } private static Member deserialize(String path) throws IOException, ClassNotFoundException { FileInputStream fileInputStream = new FileInputStream(path); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); Member member = (Member) objectInputStream.readObject(); objectInputStream.close(); fileInputStream.close(); return member; } }
Result
Member[name=Laulau,age=21,email=folaukaveinga@gmail.com] writing object state... externalizedMember=Member[name=Laulau,age=21,email=folaukaveinga@gmail.com] reading object state... dexternalizedMember=Member[name=Laulau,age=21,email=folaukaveinga@gmail.com]
4. What are the differences between Serialization and Externalization?
Externalizable provides us with writeExternal()
and readExternal()
methods that give us control on what attributes and values to serialize. Correct implementation of the Externalizable interface can improve the performance of application drastically.
Externalization | Serialization | |
UID | No need to have it but for best practice you must have it | Needs a serialVersionUID |
Storage | Store the data per attribute. | Store the whole object directly. |
Access | Provides complete control to the serialization and deserialization process. | No access |
5. How many methods does Serializable have?
Zero. Serializable is a marker interface.
6. What is a serialVersionUID? What happens when you don’t explicitly provide?
serialVersionUID is a version control id. It is basically the hashcode of the object. So if you change the object(add or remove an attribute) then the hashcode will be different so an already serialized object will not be able to deserialize. Java serialization process relies on correct serialVersionUID for recovering the state of the serialized object and throws java.io.InvalidClassException in case of serialVersionUID mismatch
When an object is serialized, the serialVersionUID is serialized along with the other contents. Later when that is deserialized, the serialVersionUID from the deserialized object is extracted and compared with the serialVersionUID of the loaded class. If the numbers do not match then, InvalidClassException is thrown.
serialVersionUID is a 64-bit hash of the class name, interface class names, methods and fields. Serialization runtime generates a serialVersionUID if you do not add one. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations and can produce different serialVersionUID in different environments.
If you don’t provide it, Java will provide it for you.
7. What happens if an object is serializable but it includes a reference to a non-serializable object?
Java will throw a NotSerializableException. To fix this issue you can do either one of these two things:
a. Make the non-serializable object serializable by making its class implement the Serializable interface.
b. Make the non-serializable object transient or static.
8. If a class is serializable but its superclass in not, what will be the state of the instance variables inherited from super class after deserialization?
The state will be its default value. For example:
int age; -> age = 0;
String name; -> name = null;
9. To serialize an array or a collection all the members of it must be serializable. True /False?
true
All standard implementations of collections List, Set and Map interface already implement java.io.Serializable. This means you do not really need to write anything specific to serialize collection objects. However, you should keep the following things in mind before you serialize a collection object – Make sure all the objects added in a collection are Serializable.
10. While serializing you want some of the members not to serialize, how do you achieve it?
If you don’t want any field to be part of the object’s state then declare it either static or transient based on your need and it will not be included during the serialization process.
Variables marked with transient are not included in the process of serialization and are not part of the object’s serialized state.
The static variables belong to a class are not part of the state of the object so they are not saved as part of the serialized object.
Why static variables are not serialized in Java?
The Java variables declared as static are not considered part of the state of an object since they are shared by all instances of that class. Saving static variables with each serialized object would have following problems
11. What should you take care of when serializing an object?
You should make sure that all the included objects are also serializable. If any of the objects is not serializable then it throws a NotSerializableException.
12. Suppose a superclass of a new class implements Serializable interface, how can you avoid new class to being serialized?
Use Externalization and exclude the new class from the serialization process.
13. What are the ways to speed up Object Serialization? How to improve Serialization performance?
The default Java Serialization mechanism is really useful, however it can have a really bad performance based on your application and business requirements. The serialization process performance heavily depends on the number and size of attributes you are going to serialize for an object. Below are some tips you can use for speeding up the marshaling and un-marshaling of objects during Java serialization process.
14. Do constructors get invoked or run at deserialization?
When an instance of a serializable class is deserialized, the constructor does not run. If constructors were invoked it will give back the initial values rather than the value they had at the time of serialization.
15. What are the compatible and incompatible changes when dealing with versioned serialized objects during serialization?
Changes to a serializable class can be compatible or incompatible. Following is the list of changes which are compatible:
List of incompatible changes:
16. What are the guidelines for using serialVersionUID?
17. Does setting the serialVersionUID class field improve Java serialization performance?
Declaring an explicit serialVersionUID field in your classes saves some CPU time only the first time the JVM process serializes a given Class. However the gain is not significant, In case when you have not declared the serialVersionUID its value is computed by JVM once and subsequently kept in a soft cache for future use.
18. Suppose you have a class in which you serialized and stored in persistence and later modified that class to add a new field. What will happen if you deserialize the object already serialized?
It depends on whether a class has its own serialVersionUID or not. As we know that if we don’t provide serialVersionUID in our code java compiler will generate it and normally it’s equal to hashCode of the object. By adding any new field there is a chance that new serialVersionUID generated for that class version is not the same as the serialized object. In this case, Java Serialization API will throw java.io.InvalidClassException
and this is the reason its recommended to have your own serialVersionUID in code and make sure to keep it same always for a single class.
1. Why is there a need for multi-threading?
Multi-threading allows your program to execute logic in parallel. For example: if you are tasked to develop an API endpoint to download a file, read from the database, run calculations, call another API, then this will be an expensive task in terms of resources and time.
As you can see, it will take 5+ seconds with the best-case scenario. This isn’t too bad but still, users expect a faster response than 5+ seconds. If we use multi-threading to execute these steps in parallel then we can decrease the response time significantly.
Now instead of 5+ seconds, our new response time is 3 seconds.
2. What is multi-threading?
Multi-threading is executing a series of logic in parallel. Example: a web server is using multi-threading to execute multiple requests from clients(web browsers or mobile apps) at the same time.
3. What is a thread?
A thread is an independent path of execution within a program. Many threads can run concurrently within a program, either asynchronously or synchronously.
4. What are the differences between a thread and a process?
Threads share memory among themselves. A process does not share memory.
Threads are lightweight compared to processes.
Context switching between threads is usually less expensive than between processes.
The cost of thread intercommunication is relatively low compared to that of process intercommunication.
Threads allow different tasks to be performed concurrently.
5. How can you create a thread?
There are two ways you can create a thread. You can extend the Thread class or implement the Runnable interface. Implementing the Runnable interface is preferred by many because it allows you to implement other interfaces or extend another class.
Using the Thread class
public class MemberThread extends Thread { @Override public void run() { super.run(); // coding to execute System.out.println("run MemberThread..."); } }
Using the Runnable interface
public class UserRunnable implements Runnable { public UserRunnable() { super(); System.out.println("UserRunnable"); } @Override public void run() { // code to execute System.out.println("running UserRunnable.."); } }
public class ThreadCreationDemo { public static void main(String[] args) { Thread userThread = new Thread(new UserRunnable()); userThread.start(); MemberThread memberThread = new MemberThread(); memberThread.start(); } }
Result
UserRunnable running UserRunnable.. start MemberThread... run MemberThread...
6. What are the different statuses of a thread?
a. NEW – a new Thread instance that was not yet started via Thread.start().
b. RUNNABLE – a running thread. It is called runnable because at any given time it could be either running or waiting for the next quantum of time from the thread scheduler. A NEW thread enters the RUNNABLE state when you call Thread.start() on it.
c. RUNNING – In this state, the thread scheduler picks the thread from the ready state, and the thread is running.
c. BLOCKED – a running thread becomes blocked if it needs to enter a synchronized section but cannot do that due to another thread holding the monitor of this section.
d. WAITING – a thread enters this state if it waits for another thread to perform a particular action. For instance, a thread enters this state upon calling the Object.wait() method on a monitor it holds, or the Thread.join() method on another thread.
e. TIMED_WAITING – same as the above, but a thread enters this state after calling timed versions of Thread.sleep(), Object.wait(), Thread.join() and some other methods.
f. TERMINATED – a thread has completed the execution of its Runnable.run() method and terminated.
The state of a Thread can be checked using the Thread.getState() method.
7. What is the difference between the Runnable interface and the Callable interface?
The Runnable interface does not have a return value or to throw unchecked exceptions.
The Callable interface has a return value. It can also throw exceptions. Callable is generally used in ExecutorService instances to start an asynchronous task and then call the returned Future instance to get its value.
FutureTask<Integer> futureTask = new FutureTask<Integer>(new CustomerCallable()); Thread customerCallableStart = new Thread(futureTask); customerCallableStart.start(); try { int result = futureTask.get(); System.out.println("result: " + result); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); }
8. What is context-switching?
In Context switching, the state of the thread or process is stored so that it can be restored and execution can be resumed from the same point later. Context switching enables multiple threads or processes to share the same CPU.
9. 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 reenters the pool of ready tasks. The scheduler then determines which task should execute next, based on priority and other factors.
10. What is the difference between the start() method and the run() method?
The start() method is used to start a newly created thread, while start() internally calls run() method.
When you invoke run() directly, the execution will run on the main thread. It won’t create a new thread for you.
11. What is the difference between user threads and daemon threads?
When we create a Thread in java program, it’s known as user thread. A daemon thread runs in the background and doesn’t prevent JVM from terminating. When there are no user threads running, JVM shutdown the program and quits. A child thread created from daemon thread is also a daemon thread.
12. How can we pause the execution of a Thread for a specific time?
We can use the Thread class sleep() method to pause the execution of a thread for a duration of time. Note that this will not stop the processing of the thread, once the thread is awake from sleep, it states gets changed to runnable and based on thread scheduling, it gets executed.
13. What do you understand about Thread Priority?
Every thread has a priority, usually higher priority thread gets precedence in execution but it depends on Thread Scheduler implementation that is OS-dependent. We can specify the priority of thread but it doesn’t guarantee that higher priority thread will get executed before lower priority thread. Thread priority is an int whose value varies from 1 to 10 where 1 is the lowest priority thread and 10 is the highest priority thread.
14. How can we make sure that the main thread is the last thread to finish in Java Program?
We can use Thread join() method to make sure all the threads created by the program is dead before finishing the main function
15. How does thread communicate with each other?
When threads share resources, communication between Threads is important to coordinate their efforts. Object class wait(), notify() and notifyAll() methods allow threads to communicate about the lock status of a resource.
16. What is the difference between wait() and sleep() method?
The wait() method releases the lock but the sleep() method doesn’t.
The wait() method is defined in Object class but the sleep() method is from the Thread class.
17. Is it possible to start a thread twice?
No, we cannot restart the thread, as once a thread started and executed, it goes to the Dead state. Therefore, if we try to start a thread twice, it will give a runtime Exception “java.lang.IllegalThreadStateException”.
18. What are daemon threads?
Daemon threads are low priority threads that provide the background support and services to the user threads. Daemon thread gets automatically terminated by the JVM if the program remains with the daemon thread only, and all other user threads are ended/died. We can make a user thread a daemon thread by calling the setDaemon() method. We can only do this before the thread is starting otherwise it will throw an exception. There are two methods for daemon thread available in the Thread class.
19. Why Thread sleep() and yield() methods are static?
Thread sleep() and yield() methods work on the currently executing thread. So there is no point in invoking these methods on some other threads that are in a wait state. That’s why these methods are made static so that when this method is called statically, it works on the currently executing thread and avoid confusion to the programmers who might think that they can invoke these methods on some non-running threads.
20. How can we achieve thread-safety in Java?
There are several ways to achieve thread-safety in java – synchronization, atomic concurrent classes, implementing concurrent Lock interface, using the volatile keyword, using immutable classes and Thread-safe classes.
21. What is the volatile keyword in Java
It is used to mark a variable as “being stored in main memory”. More precisely that means, that every read of a volatile variable will be read from the computer’s main memory, and not from the CPU cache and that every a write happens to a volatile variable will be written to main memory, and not just to the CPU cache.
A change in a volatile variable is visible to all other threads so one variable can be used by one thread at a time.
In a multithreaded application where the threads operate on non-volatile variables, each thread may copy variables from main memory into a CPU cache while working on them, for performance reasons. If your computer contains more than one CPU, each thread may run on a different CPU. That means, that each thread may copy the variables into the CPU cache of different CPUs.
With non-volatile variables, there are no guarantees about when the Java Virtual Machine (JVM) reads data from the main memory into CPU caches or writes data from CPU caches to the main memory. This can cause problems.
Using volatile is sometimes not enough. It is recommended to use synchronized to guarantee that the reading and writing of the variable are atomic.
22. Which way is more preferred – Synchronized method or Synchronized block?
The synchronized block is the more preferred way because it doesn’t lock the Object, synchronized methods lock the Object and if there are multiple synchronization blocks in the class, even though they are not related, it will stop them from execution and put them in wait state to get the lock on Object.
23. Can you synchronize a static method?
Yes, if you do you will be synchronizing the class so only one thread can enter into a synchronized static method.
24. What is Threadlocal?
The Threadlocal class enables you to create variables that can only be read and written by the same thread. Thus, even if two threads are executing the same code, and the code has a reference to the same Threadlocal variable, the two threads cannot see each other’s Threadlocal variables.
If we want to use an ExecutorService and submit a Runnable to it, using ThreadLocal will yield non-deterministic results – because we do not have a guarantee that every Runnable action for a given userId will be handled by the same thread every time it is executed.
Use it when you have some object that is not thread-safe, but you want to avoid synchronizing access to that object.
public class UserThreadLocal extends Thread { private static final AtomicInteger id = new AtomicInteger(0); ThreadLocal<String> privateName = ThreadLocal.withInitial(() -> " John--" + id.incrementAndGet()); @Override public void run() { super.run(); System.out.println("run..." + privateName.get()); } }
25. What is Java Thread Dump, How can we get Java Thread dump of a Program?
A thread dump is a list of all the threads active in the JVM, thread dumps are very helpful in analyzing bottlenecks in the application and analyzing deadlock situations. There are many ways using which we can generate Thread dump – Using Profiler, Kill -3 command, jstack tool, etc. I prefer jstack tool to generate thread dump of a program because it’s easy to use and comes with JDK installation. Since it’s a terminal-based tool, we can create a script to generate thread dump at regular intervals to analyze it later on.
26. 30 commonly asked interview questions related to Java concurrency
Question: What is concurrency in Java? Answer: Concurrency is the ability of a program to execute multiple tasks concurrently. It allows for efficient utilization of system resources and improved program performance.
Question: What is a thread in Java? Answer: A thread is a lightweight unit of execution within a program. It allows multiple parts of a program to execute concurrently.
Question: How can you create a thread in Java? Answer: There are two ways to create a thread in Java: by extending the Thread
class or by implementing the Runnable
interface.
Question: What is the difference between the start()
and run()
methods of a thread? Answer: The start()
method is used to start a new thread and internally calls the run()
method, which contains the code that will be executed by the thread.
Question: What is thread synchronization? Answer: Thread synchronization is the coordination of multiple threads to ensure their safe and orderly execution. It is used to prevent race conditions and ensure data consistency.
Question: How can you synchronize a block of code in Java? Answer: You can use the synchronized
keyword to synchronize a block of code by enclosing it within a synchronized block or by declaring a synchronized method.
Question: What is the purpose of the volatile
keyword in Java? Answer: The volatile
keyword is used to declare a variable whose value may be modified by multiple threads. It ensures that changes to the variable are immediately visible to other threads.
Question: What is a race condition? Answer: A race condition occurs when multiple threads access and modify shared data concurrently, leading to unpredictable results. It can be resolved using synchronization mechanisms.
Question: What are the differences between wait()
and sleep()
methods in Java? Answer: The wait()
method is used for inter-thread communication, allowing a thread to wait until another thread notifies it. The sleep()
method is used to pause the execution of a thread for a specified amount of time.
Question: What is a deadlock? Answer: A deadlock occurs when two or more threads are blocked forever, each waiting for a resource that the other thread holds. Deadlocks can be avoided by careful resource allocation and proper synchronization.
Question: Explain the concept of thread pooling. Answer: Thread pooling involves creating a pool of reusable threads to execute tasks. It reduces the overhead of creating and destroying threads for each task, resulting in improved performance.
Question: What is the Executor
framework in Java? Answer: The Executor
framework provides a higher-level abstraction for managing and executing threads. It decouples task submission from execution policies.
Question: What is the purpose of the Callable
interface in Java? Answer: The Callable
interface is similar to the Runnable
interface, but it can return a result and throw checked exceptions. It is used with the ExecutorService
to execute tasks and retrieve results.
Question: What is the Java Memory Model (JMM)? Answer: The Java Memory Model defines the rules and guarantees for the interaction of threads and memory. It ensures visibility and ordering of memory operations across multiple threads.
Question: Explain the concept of atomic operations in Java. Answer: Atomic operations are indivisible operations that are performed as a single unit of execution. They ensure that operations on shared data are thread-safe and free from race conditions.
Question: What is a semaphore in Java concurrency? Answer: A semaphore is a synchronization primitive that controls access to a shared resource. It allows aContinuing from the previous response, here are more Java concurrency interview questions along with their answers:
Question: What is the purpose of the CountDownLatch
class in Java? Answer: The CountDownLatch
class is used to synchronize threads by allowing them to wait until a certain number of operations or events have occurred before proceeding.
Question: What is the purpose of the CyclicBarrier
class in Java? Answer: The CyclicBarrier
class is used to synchronize multiple threads by making them wait at a barrier until all threads have reached it. Once all threads have arrived, they can proceed simultaneously.
Question: What is the purpose of the ReentrantLock
class in Java? Answer: The ReentrantLock
class provides a more advanced locking mechanism than the synchronized
keyword. It allows for finer-grained control over locking and supports features like fairness and interruptible locks.
Question: What is the purpose of the ReadWriteLock
interface in Java? Answer: The ReadWriteLock
interface provides a way to have multiple threads simultaneously read from a shared resource, while only allowing one thread to write to it at a time. It improves concurrency in scenarios with frequent reads and infrequent writes.
Question: What is the purpose of the BlockingQueue
interface in Java? Answer: The BlockingQueue
interface provides a thread-safe queue implementation that supports blocking operations, such as waiting for elements to become available or waiting for space to become available for adding elements.
Question: What is the purpose of the ThreadLocal
class in Java? Answer: The ThreadLocal
class provides a way to create thread-local variables, where each thread has its own copy of the variable. It is useful for maintaining thread-specific data.
Question: What is the purpose of the volatile
keyword in relation to multi-threading? Answer: The volatile
keyword ensures that a variable’s value is always read from and written to main memory, rather than being cached in a thread’s local cache. It guarantees visibility of the variable’s latest value across multiple threads.
Question: What is the purpose of the join()
method in Java? Answer: The join()
method is used to make a calling thread wait until a target thread completes its execution. It is often used to ensure that the main thread waits for all worker threads to finish before proceeding.
Question: What is the purpose of the notify()
and notifyAll()
methods in Java? Answer: The notify()
method is used to wake up a single thread that is waiting on the same object’s monitor, while the notifyAll()
method wakes up all threads waiting on the object’s monitor. These methods are used for inter-thread communication.
Question: Explain the concept of thread starvation and how it can be avoided. Answer: Thread starvation occurs when a thread is perpetually denied access to the CPU or resources it needs. It can be avoided by implementing proper thread scheduling, fairness policies, and resource management.
Question: Explain the concept of thread starvation and how it can be avoided. Answer: Thread starvation occurs when a thread is perpetually denied access to the CPU or resources it needs. It can be avoided by implementing proper thread scheduling, fairness policies, and resource management.
Question: What is the purpose of the ForkJoinPool
class in Java? Answer: The ForkJoinPool
class is used for parallelizing tasks that can be divided into subtasks and executed concurrently. It is based on the divide-and-conContinuing from the previous response, here are more Java concurrency interview questions along with their answers:
Question: What is the purpose of the CompletableFuture
class in Java? Answer: The CompletableFuture
class provides a way to handle asynchronous computations and compose them in a non-blocking manner. It allows for chaining and combining asynchronous operations.
Question: Explain the concept of non-blocking and asynchronous programming in Java. Answer: Non-blocking and asynchronous programming techniques allow for concurrent execution of tasks without blocking the calling thread. Non-blocking operations return immediately, and the result is delivered at a later time, often through callbacks or promises.