Java Multithreading
Java Multithreading
Multithreading and Synchronization are considered as the typical chapter in java programming. In game
development companies, multithreading related interview questions are asked mostly. A list of frequently asked
java multithreading and concurrency interview questions is given below.
1) What is multithreading?
Multithreading is a process of executing multiple threads simultaneously. Multithreading is used to obtain the
multitasking. It consumes less memory and gives the fast and efficient performance. Its main advantages are:
More details.
More details.
A Program in the execution is called the process whereas; A thread is a subset of the process
Process have different address space in memory, while threads contain a shared address space.
Any change in Parent process doesn't affect the child process whereas changes in parent thread
can affect the child thread.
The 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.
Multithreading allows an application/program to be always reactive for input, even already running
with some background tasks
Multithreading provides better utilization of cache memory as threads share the common memory
resources.
Multithreading reduces the number of the required server as one server can execute multiple
threads at a time.
1. New: In this state, 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.
2. Runnable: In this state, the thread is ready to run after calling the start() method. However, the
thread is not yet selected by the thread scheduler.
3. Running: In this state, the thread scheduler picks the thread from the ready state, and the thread is
running.
4. Waiting/Blocked: In this state, a thread is not running but still alive, or it is waiting for the other
thread to finish.
5. Dead/Terminated: A thread is in terminated or dead state when the run() method exits.
11) Differentiate between the Thread class and Runnable interface for creating a
Thread?
The Thread can be created by using two ways.
However, the primary differences between both the ways are given below:
By extending the Thread class, we cannot extend any other class, as Java does not allow multiple
inheritances while implementing the Runnable interface; we can also extend other base class(if
required).
By extending the Thread class, each of thread creates the unique object and associates with it while
implementing the Runnable interface; multiple threads share the same object
Thread class provides various inbuilt methods such as getPriority(), isAlive and many more while the
Runnable interface provides a single method, i.e., run().
More details.
Syntax:
When we call the sleep() method, it pauses the execution of the current thread for the given time and gives
priority to another thread(if available). Moreover, when the waiting time completed then again previous thread
changes its state from waiting to runnable and comes in running state, and the whole process works so on till the
execution doesn't complete.
wait() sleep()
1) The wait() method is defined in Object class. The sleep() method is defined in Thread class.
2) The wait() method releases the lock. The sleep() method doesn't release the lock.
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 runtimeException "java.lang.IllegalThreadStateException". Consider
the following example.
Output
More details.
More details.
public void setDaemon(boolean status): It used to mark the thread daemon thread or a user
thread.
More details.
18)Can we make the user thread as daemon thread if the thread is started?
No, if you do so, it will throw IllegalThreadStateException. Therefore, we can only create a daemon thread before
starting the thread.
Output
More details.
public�void�addShutdownHook(Thread�hook){}��
Runtime r=Runtime.getRuntime();
r.addShutdownHook(new MyThread());
Shutdown hooks initialized but can only be started when JVM shutdown occurred.
Shutdown hooks are more reliable than the finalizer() because there are very fewer chances that
shutdown hooks not run.
The shutdown hook can be stopped by calling the halt(int) method of Runtime class.
More details.
More details.
When the multiple threads try to do the same task, there is a possibility of an erroneous�result, hence to remove
this issue, Java uses the process of synchronization which allows only one thread to be executed at a time.
Synchronization can be achieved in three ways:
by synchronized block
by static synchronization
More details.
More details.
23)Can Java object be locked down for exclusive use by a given thread?
Yes. You can lock an object by putting it in a "synchronized" block. The locked object is inaccessible to any thread
other than the one that explicitly claimed it.
More details.
Avoid Nested lock: Nested lock is the common reason for deadlock as deadlock occurs when we
provide locks to various threads so we should give one lock to only one thread at some particular
time.
Avoid unnecessary locks: we must avoid the locks which are not required.
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.
Java thread scheduler also works for deciding the following for a thread:
Synchronization
Using Volatile keyword
Using a lock based mechanism
Use of atomic wrapper classes
Java Thread pool represents a group of worker threads, which are waiting for the task to be
allocated.
Threads in the thread pool are supervised by the service provider which pulls one thread from the
pool and assign a job to it.
After completion of the given task, thread again came to the thread pool.
The size of the thread pool depends on the total number of threads kept at reserve for execution.
Executor
FarkJoinPool
ExecutorService
ScheduledExecutorService
Future
TimeUnit(Enum)
CountDownLatch
CyclicBarrier
Semaphore
ThreadFactory
BlockingQueue
DelayQueue
Locks
Phaser
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
Output
Running Thread!
Thread Completed
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
new Thread(i).start();
new Thread(r).start();
Thread.sleep(2000);
}
@Override
public void run() {
Random random = new Random();
try {
int result = random.nextInt(200);
Thread.sleep(1000);
queue.put(result);
System.out.println("Added: " + result);
result = random.nextInt(10);
Thread.sleep(1000);
queue.put(result);
System.out.println("Added: " + result);
result = random.nextInt(50);
Thread.sleep(1000);
queue.put(result);
System.out.println("Added: " + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
try {
System.out.println("Removed: " + queue.take());
System.out.println("Removed: " + queue.take());
System.out.println("Removed: " + queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Output
Added: 96
Removed: 96
Added: 8
Removed: 8
Added: 5
Removed: 5
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ProducerConsumerProblem {
public static void main(String args[]){
//Creating shared object
BlockingQueue sharedQueue = new LinkedBlockingQueue();
@Override
public void run() {
for(int i=0; i<10; i++){
try {
System.out.println("Produced: " + i);
sharedQueue.put(i);
} catch (InterruptedException ex) {
Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void run() {
while(true){
try {
System.out.println("Consumed: "+ sharedQueue.take());
} catch (InterruptedException ex) {
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Output
Produced: 0
Produced: 1
Produced: 2
Produced: 3
Produced: 4
Produced: 5
Produced: 6
Produced: 7
Produced: 8
Produced: 9
Consumed: 0
Consumed: 1
Consumed: 2
Consumed: 3
Consumed: 4
Consumed: 5
Consumed: 6
Consumed: 7
Consumed: 8
Consumed: 9
38) What is the difference between Java Callable interface and Runnable
interface?
The Callable interface and Runnable interface both are used by the classes which wanted to execute with
multiple threads. However, there are two main differences between the both :
A Callable <V> interface can return a result, whereas the Runnable interface cannot return any result.
A Callable <V> interface can throw a checked exception, whereas the Runnable interface cannot
throw checked exception.
A Callable <V> interface cannot be used before the Java 5 whereas the Runnable interface can be
used.
The Atomic action is the operation which can be performed in a single unit of a task without any
interference of the other operations.
The Atomic action cannot be stopped in between the task. Once started it fill stop after the
completion of the task only.
All reads and writes operation for the primitive variable (except long and double) are the atomic
operation.
All reads and writes operation for the volatile variable (including long and double) are the atomic
operation.
Lock interface provides the guarantee of sequence in which the waiting thread will be given the
access, whereas the synchronized block doesn't guarantee it.
Lock interface provides the option of timeout if the lock is not granted whereas the synchronized
block doesn't provide that.
The methods of Lock interface, i.e., Lock() and Unlock() can be called in different methods whereas
single synchronized block must be fully contained in a single method.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
try {
e.submit(new Thread());
System.out.println("Shutdown executor");
e.shutdown();
e.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
System.err.println("tasks interrupted");
} finally {
if (!e.isTerminated()) {
System.err.println("cancel non-finished tasks");
}
e.shutdownNow();
System.out.println("shutdown finished");
}
}
try {
Long duration = (long) (Math.random() * 20);
System.out.println("Running Task!");
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
Output
Shutdown executor
shutdown finished
Asynchronous Programming: In Asynchronous programming, one job can be completed by multiple threads
and hence it provides maximum usability of the various threads.
Syntax:
Java Future interface: Java Future interface gives the result of a concurrent process. The Callable interface
returns the object of java.util.concurrent.Future.
get(): It waits for the time if execution not completed and then retrieved the result.
isCancelled(): It returns the Boolean value as it returns true if the task was canceled before the
completion.
isDone(): It returns true if the job is completed successfully else returns false.
Syntax