JDBC Interview Questions with Answers

What is thread and multi-threading? How is process different from the thread?

A thread is a small subprocess that runs in the background. It follows a separate path of execution because each thread operates in a different stack frame. Multiple threads can exist in a process. Threads share process resources, yet they still run on their own.

Multithreading is the process of running many threads at the same time. To achieve multitasking, multithreading is used. It uses less memory and provides quick and efficient results. Process is different from thread by :

  • The process refers to the execution of a programme, whereas a thread is a subset of the process.
  • Threads are a subset of processes, whereas processes are independent.
  • Processes have their own memory address space, whereas threads have a shared address space.
  • Context switching is faster between the threads as compared to processes.
  • Inter-process communication is slower and expensive than inter-thread communication.
  • Changes to the parent process have no impact on the child process, however changes to the parent thread can have an impact on the child thread.

Explain Thread priorities and their rules?

It determines how each thread should be treated with respect to the others. Thread priorities are integers that specify the relative priority of one thread to another. As an absolute value, a priority is meaningless; a higher-priority thread doesn’t run any faster than a lower-priority thread if it is the only thread running. Instead, a thread’s priority is used to decide when to switch from one running thread to the next. This is called a context switch. There are two rules to prioritize thread :

  • A thread can voluntarily relinquish control : This is done by explicitly yielding, sleeping, or blocking on pending I/O. In this scenario, all other threads are examined, and the highest-priority thread that is ready to run is given the CPU.
  • A thread can be preempted by a higher-priority thread : In this case, a lower-priority thread that does not yield the processor is simply preempted—no matter what it is doing by a higher-priority thread. Basically, as soon as a higher-priority thread wants to run, it does. This is called preemptive multitasking.

Explain the method to create a thread?

There are two ways in which thread can be created :

  • Implementing Runnable The easiest way to create a thread is to create a class that implements the Runnable interface. Runnable abstracts a unit of executable code. You can construct a thread on any object that implements Runnable. To implement Runnable, a class need only implement a single method called run()
// Create a second thread.
class NewThread implements Runnable {
    Thread t;
    NewThread() {
        // Create a new, second thread
        t = new Thread(this, "Demo Thread");
        System.out.println("Child thread: " + t);
        t.start(); // Start the thread
    }
    // This is the entry point for the second thread.
    public void run() {
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Child Thread: " + i);
                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            System.out.println("Child interrupted.");
        }
        System.out.println("Exiting child thread.");
    }
}
class ThreadDemo {
    public static void main(String args[ ] ) {
        new NewThread(); // create a new thread
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Main Thread: " + i);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("Main thread interrupted.");
        }
        System.out.println("Main thread exiting.");
    }
}

Inside NewThread’s constructor, a new Thread object is created by the following statement:

t = new Thread(this, “Demo Thread”);

  • Extending Thread The second way to create a thread is to create a new class that extends Thread, and then to create an instance of that class. The extending class must override the run( ) method, which is the entry point for the new thread. It must also call start( ) to begin execution of the new thread.
// Create a second thread by extending Thread
class NewThread extends Thread {
    NewThread() {
        // Create a new, second thread
        super("Demo Thread");
        System.out.println("Child thread: " + this);
        start(); // Start the thread
    }
    // This is the entry point for the second thread.
    public void run() {
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Child Thread: " + i);
                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            System.out.println("Child interrupted.");
        }
        System.out.println("Exiting child thread.");
    }
}
class ExtendThread {
    public static void main(String args[]) {
        new NewThread(); // create a new thread
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Main Thread: " + i);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("Main thread interrupted.");
        }
        System.out.println("Main thread exiting.");
    }
}

This program generates the same output as the preceding version. As you can see, the child thread is created by instantiating an object of NewThread, which is derived from Thread.

Explain the life cycle of thread in Java?

A thread can have one of the following stages :

  • New A Thread class object is created using a new operator, but the thread is not alive. Thread doesn’t start until we call the start() method.
  • Runnable The thread is ready to run after calling the start() method. Threads in this state are either running or ready to run, but they’re waiting for resource allocation from the system. The Thread-Scheduler (component of the JVM) allocates a predetermined amount of time to each thread in a multi-threaded system. As a result, it runs for a set amount of time before giving control to other RUNNABLE threads.

  • Running The thread scheduler picks the thread from the ready state, and the thread is running. From the running state, a thread can enter into the waiting/blocked state, runnable or the final dead state.

  • Waiting/Blocked In three conditions, a thread enters a not runnable state: (i) When a thread has called the wait() method on itself and is waiting for another thread to wake it up or notify it. (ii) When the sleep() method is used on a thread, it tells it to sleep for a set amount of time. (iii) When a thread calls the join() method on another thread, the first thread is forced to wait until the second thread completes its execution. When a thread is in one of the three states indicated above, it is pushed into a blocking/waiting or sleeping mode, and the thread is no longer eligible to run. In any of these states, the thread is still considered to be alive. When thread gets out of waiting, blocking or sleeping state, it re-enters into the runnable state.

  • Dead/Terminated In the lifecycle of a thread, this is the final state. When a thread completes the run() method successfully, it enters the dead state. In this state, it is considered to be dead, and attempting to call start() on a dead thread will result in an IllegalThreadStateException.

How can one thread know when another thread has ended?

Two ways exist to determine whether a thread has finished. First, you can call isAlive() on the thread. This method is defined by Thread, and its general form is :

final boolean isAlive()

The isAlive() method returns true if the thread upon which it is called is still running. It returns false otherwise.

While isAlive() is occasionally useful, the method that you will more commonly use to wait for a thread to finish is called join(), shown here:

final void join() throws InterruptedException

This method waits until the thread on which it is called terminates. Its name comes from the concept of the calling thread waiting until the specified thread joins it. Additional forms of join( ) allow you to specify a maximum amount of time that you want to wait for the specified thread to terminate.

Explain sleep() method and its working? How can we interrupt a thread?

The sleep() method in Java is used to block a thread for a set amount of time, i.e., it pauses the thread’s execution for a specific amount of time.

There are two methods:

public static void sleep(long milliseconds)throws InterruptedException public static void sleep(long milliseconds, int nanos)throws InterruptedException

When we use the sleep() method, it pauses the current thread’s execution for the specified amount of time and provides priority to another thread (if available). Furthermore, after the waiting period is up, the previous thread changes its state from waiting to runnable and enters the running state, and the process continues in this manner until the execution is complete.

When we want to get a thread out of its sleep or wait state, we should interrupt it. Interrupting a thread is done by invoking interrupt(), which throws the InterruptedException.

What are daemon threads? Can we make the user thread as daemon thread if the thread is started?

The daemon threads are low-priority threads that provide support and services to the user threads in the background. If the programme only uses the daemon thread and all other user threads are terminated/died, the JVM will immediately terminate the daemon thread.

No, we can’t make the user thread as daemon thread if the thread is started because doing it will result in an IllegalThreadStateException. As a result, we can only start the thread after creating a daemon thread.

What is the deadlock condition? State the ways we can detect and avoid deadlock condition?

It’s a situation where each thread is waiting for a resource that is being held by another thread. In this case, neither thread is executed nor is it given the opportunity to be executed. Instead, all of the threads are in a state of universal waiting. Deadlock is a complex scenario that can cause our programming to break at runtime.

We can identify a deadlock issue by running the code on cmd and collecting the Thread Dump; if the code contains any deadlocks, a notification will be displayed on cmd.

Ways to avoid deadlock conditions are :

  • Avoid unnecessary locks : We must avoid the locks which are not required.
  • Avoid nested locks : Nested locks are a typical cause of deadlock, as they arise when we issue locks to several threads at the same time, while we should only give one lock to one thread at a time.
  • Using thread join : Thread join helps to wait for a thread until another thread doesn’t finish its execution so we can avoid deadlock by maximum use of join method.

What is synchronization and race condition?

Synchronization is the ability to manage several threads’ access to a shared resource. It’s used for:

  • To prevent thread interference.
  • To prevent consistency problem.

When numerous threads attempt to perform the same operation, an incorrect outcome is possible; hence, Java employs the synchronization mechanism, which permits only one thread to be run at a time.synchronized method, synchronized block and static synchronization these are the three approaches to accomplish synchronization.

A race condition is an issue that happens in multi-threaded programming when many threads run at the same time and access a shared resource. The Race condition can be avoided with adequate synchronization.

Explain Thread Scheduler?

When we construct threads in Java, we use a Thread Scheduler, which is part of the JVM, to supervise them. The thread scheduler is only in charge of choosing which threads should run. The thread scheduler employs two scheduling mechanisms: preemptive and time slicing. It also helps us to decide the priority of the thread, waiting time of the thread, and the nature of the thread.