Showing posts with label java threading. Show all posts
Showing posts with label java threading. Show all posts

java interview with Investment bank - 5


Getting a new job looks very tedious work and it needs the preparation. better you are prepared important topics and you have more chances of winning the interview. It is not just chance, its your hard work which makes way for you. After long time, again I started giving interviews for my next move. This time I am looking for more senior role similar to technical manager but still I need to clear java technical round and here are those questions:





**Wining Attitude is the Key for interviews**




Questions :-

1) Your Current project and Role\ Responsibilities?

2) Explain your current application and it's design?

3) Explain JMS Transaction and how you can control transaction from you receive the message to persisting data into DB?

4) How to handle DB transaction in Spring?

5) What is benefits of Spring?

6) HashMap VS TreeMap which one to use, how to decide?

7) How to create immutable Objects?

8) What is annotation and what is benefits?

9) How JIXB xml parsing works?

10) Threading, what happens if same object instance is read by two threads?

11) If one reader thread and one writer thread act on one objects double variable and writer thread is trying to update the value from 4 to 5. if both does this call at same time what value reader thread will see for double variable?  [ Hint double writing is not atomic in java]

12) If you have java application cache where  you have 1000 reads  but very less writes into cache, which locking you will you and how? tell me the class name?

Suddenly interview moved to web application technology side and they asked these questions:

1) What is application context in web app?

2) What dispatcher servlet do in Spring mvc?


Two design discussion

1) Large file having text and how we can find the word count in the file and which collection to use?

2) We have Professor , Course and Student table and one professor can take multiple course and one student can take multiple courses. How to find out which professor is having maximum students write query and table design?

Best of luck for any upcoming interviews. Important topic to cover for interview -

1) JAVA 1.5 details
2) Java Collection Interview questions
3) XML PArsing
4) JDBC Interview Questions
5) Hibernate interview questions
6) Java Threading questions
7) Java Concurrency questions.
8) JMS interview questions.
9) Spring Framework


Java Concurrency

Java Concurrency interview question- In year 2004 when technology gurus said innovation in Java is gone down and Sun Microsystems [Now Oracle] came with the Tiger release with very important changes with in java 1.5 and most important feature was Concurrency and programming features. This is hot topic for java interviews from past few years. Interviewers are mainly focused on java 1.5 concurrent package and they can ask how to use these changes and what are the benefits. They will focus on how concurrency is better than synchronisation and how executors are better than old java thread implementation? How you can avoid locks ? and What is java memory model changes for volatile etc. In investment banks we need to work on multithreaded applications due to high volume so clear understanding of this topic is very important. This topic is key for clearing any core java interview.

Most of these features are implemented in the new java.util.concurrent packages. There are also new concurrent data structures in the Java Collections Framework.
  • Lock objects support locking idioms that simplify many concurrent applications.
  • Executors define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.
  • Concurrent collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.
  • Atomic variables have features that minimize synchronization and help avoid memory consistency errors.
  • ThreadLocalRandom (in JDK 7) provides efficient generation of pseudorandom numbers from multiple threads.


1. What is Synchronized Methods ?
   The Java programming language provides two basic synchronization idioms: synchronized methods and synchronized statements. The more complex of the two, synchronized statements, are described in the next section. This section is about synchronized methods.
To make a method synchronized, simply add the synchronized keyword to its declaration:
public class SynchronizedCounter {
    private int c = 0;
    public synchronized void increment() {
       c++;
    }
    public void decrement() {
       synchronized(this){
        c--;
       }
    }
    public synchronized int value() {
       return c;
   }
}
If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:
• First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
• Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
   Note that constructors cannot be synchronized — using the synchronized keyword with a constructor is a syntax error. Synchronizing constructors doesn't make sense, because only the thread that creates an object should have access to it while it is being constructed.

2. What is Intrinsic Locks and Synchronization ?
   Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.
  Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
  When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquistion of the same lock.

3. What is Reentrant Synchronization ?
  Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.

4. What is Deadlock ?
  Deadlock describes a situation where two or more threads are blocked forever, waiting for each other. In below example method m1 and m2 both are taking lock of Integer and String class in different order and blocking each other for ever.
  This deadlock can be solved by putting same order of lock for Integer and String class in method m1 and m2. 

5. What is Starvation and Livelock ?
Starvation
Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.
Livelock
A thread often acts in response to the action of another thread. If the other thread's action is also a response to the action of another thread, then livelock may result. As with deadlock, livelocked threads are unable to make further progress. However, the threads are not blocked — they are simply too busy responding to each other to resume work. This is comparable to two people attempting to pass each other in a corridor: Alphonse moves to his left to let Gaston pass, while Gaston moves to his right to let Alphonse pass. Seeing that they are still blocking each other, Alphone moves to his right, while Gaston moves to his left. They're still blocking each other, so...

6. What is Immutable Objects ?
An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code.
Immutable objects are particularly useful in concurrent applications. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state.
Programmers are often reluctant to employ immutable objects, because they worry about the cost of creating a new object as opposed to updating an object in place. The impact of object creation is often overestimated, and can be offset by some of the efficiencies associated with immutable objects. These include decreased overhead due to garbage collection, and the elimination of code needed to protect mutable objects from corruption.
The following subsections take a class whose instances are mutable and derives a class with immutable instances from it. In so doing, they give general rules for this kind of conversion and demonstrate some of the advantages of immutable objects.

7. What should be Strategy for Defining Immutable Objects ?
The following rules define a simple strategy for creating immutable objects. Not all classes documented as "immutable" follow these rules. This does not necessarily mean the creators of these classes were sloppy — they may have good reason for believing that instances of their classes never change after construction. However, such strategies require sophisticated analysis and are not for beginners.
1. Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
2. Make all fields final and private.
3. Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
4. If the instance fields include references to mutable objects, don't allow those objects to be changed:
5. Don't provide methods that modify the mutable objects.
6. Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.

8. What are High Level Concurrency Objects ?
So far, this we have focused on the low-level APIs that have been part of the Java platform from the very beginning. These APIs are adequate for very basic tasks, but higher-level building blocks are needed for more advanced tasks. This is especially true for massively concurrent applications that fully exploit today's multiprocessor and multi-core systems.
In this section we'll look at some of the high-level concurrency features introduced with version 5.0 of the Java platform. Most of these features are implemented in the new java.util.concurrent packages. There are also new concurrent data structures in the Java Collections Framework.
• Lock objects support locking idioms that simplify many concurrent applications.
• Executors define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.
• Concurrent collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.
• Atomic variables have features that minimize synchronization and help avoid memory consistency errors.
• ThreadLocalRandom (in JDK 7) provides efficient generation of pseudorandom numbers from multiple threads

9. What is Executors ?
In large-scale applications, it makes sense to separate thread management and creation from the rest of the application. Objects that encapsulate these functions are known as executors. The following subsections describe executors in detail.
• Executor Interfaces define the three executor object types.
• Thread Pools are the most common kind of executor implementation.
• Fork/Join is a framework (new in JDK 7) for taking advantage of multiple processors.
Executor Interfaces
The java.util.concurrent package defines three executor interfaces:
• Executor, a simple interface that supports launching new tasks.
• ExecutorService, a subinterface of Executor, which adds features that help manage the lifecycle, both of the individual tasks and of the executor itself.
• ScheduledExecutorService, a subinterface of ExecutorService, supports future and/or periodic execution of tasks.
Typically, variables that refer to executor objects are declared as one of these three interface types, not with an executor class type.

Below is the example of ExecutorService using cachedThreadPool. This is using Callable instance, which does the task and return the result to calling programme.
  
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ThreadWithResultExample {
 static ExecutorService exec = Executors.newCachedThreadPool();
 public static void main(String...strings){
  Future result = exec.submit(new Worker());
  try {
  System.out.println(result.get());
 } catch (InterruptedException e) {
  e.printStackTrace();
 } catch (ExecutionException e) {
  e.printStackTrace();
 }
  exec.shutdown();
 }
}

class Worker implements Callable {
 @Override
 public String call() throws Exception {
  return (String) "result";
 }

10. What is Thread Pools ?
Most of the executor implementations in java.util.concurrent use thread pools, which consist of worker threads. This kind of thread exists separately from the Runnable and Callable tasks it executes and is often used to execute multiple tasks.Using worker threads minimizes the overhead due to thread creation. Thread objects use a significant amount of memory, and in a large-scale application, allocating and deallocating many thread objects creates a significant memory management overhead.One common type of thread pool is the fixed thread pool. This type of pool always has a specified number of threads running; if a thread is somehow terminated while it is still in use, it is automatically replaced with a new thread. Tasks are submitted to the pool via an internal queue, which holds extra tasks whenever there are more active tasks than threads.   
  An important advantage of the fixed thread pool is that applications using it degrade gracefully. To understand this, consider a web server application where each HTTP request is handled by a separate thread. If the application simply creates a new thread for every new HTTP request, and the system receives more requests than it can handle immediately, the application will suddenly stop responding to all requests when the overhead of all those threads exceed the capacity of the system. With a limit on the number of the threads that can be created, the application will not be servicing HTTP requests as quickly as they come in, but it will be servicing them as quickly as the system can sustain.  
  A simple way to create an executor that uses a fixed thread pool is to invoke the newFixedThreadPool factory method in java.util.concurrent.Executors This class also provides the following factory methods:
•  The newCachedThreadPool method creates an executor with an expandable thread pool. This executor is suitable for applications that launch many short-lived tasks.
•  The newSingleThreadExecutor method creates an executor that executes a single task at a time.
•  Several factory methods are ScheduledExecutorService versions of the above executors.
If none of the executors provided by the above factory methods meet your needs, constructing instances of java.util.concurrent.ThreadPoolExecutor or java.util.concurrent.ScheduledThreadPoolExecutor will give you additional options.

11. What is Fork/Join ?
New in the Java SE 7 release, the fork/join framework is an implementation of the ExecutorService interface that helps you take advantage of multiple processors. It is designed for work that can be broken into smaller pieces recursively. The goal is to use all the available processing power to make your application wicked fast.
As with any ExecutorService, the fork/join framework distributes tasks to worker threads in a thread pool. The fork/join framework is distinct because it uses a work-stealing algorithm. Worker threads that run out of things to do can steal tasks from other threads that are still busy.
The center of the fork/join framework is the ForkJoinPool class, an extension of AbstractExecutorService. ForkJoinPool implements the core work-stealing algorithm and can execute ForkJoinTasks.

Basic Use

Using the fork/join framework is simple. The first step is to write some code that performs a segment of the work. Your code should look similar to this:
if (my portion of the work is small enough)
     do the work directly
else
     split my work into two pieces
invoke the two pieces and wait for the results

Wrap this code as a ForkJoinTask subclass, typically as one of its more specialized types RecursiveTask(which can return a result) or RecursiveAction.
After your ForkJoinTask is ready, create one that represents all the work to be done and pass it to the invoke() method of a ForkJoinPool instance.

12. What is Concurrent Collections ?
The java.util.concurrent package includes a number of additions to the Java Collections Framework. These are most easily categorized by the collection interfaces provided:
• BlockingQueue defines a first-in-first-out data structure that blocks or times out when you attempt to add to a full queue, or retrieve from an empty queue.
• ConcurrentMap is a subinterface of java.util.Map that defines useful atomic operations. These operations remove or replace a key-value pair only if the key is present, or add a key-value pair only if the key is absent. Making these operations atomic helps avoid synchronization. The standard general-purpose implementation of ConcurrentMap is ConcurrentHashMap, which is a concurrent analog of HashMap.
• ConcurrentNavigableMap is a subinterface of ConcurrentMap that supports approximate matches. The standard general-purpose implementation of ConcurrentNavigableMap is ConcurrentSkipListMap, which is a concurrent analog of TreeMap.
    All of these collections help avoid Memory Consistency Errors by defining a happens-before relationship between an operation that adds an object to the collection with subsequent operations that access or remove that object.
13. Can you pass a Thread object to Executor.execute? Would such an invocation make sense? Why or why not ?
Thread implements the Runnable interface, so you can pass an instance of Thread to Executor.execute. However it doesn't make sense to use Thread objects this way. If the object is directly instantiated from Thread, its run method doesn't do anything. You can define a subclass of Thread with a useful run method — but such a class would implement features that the executor would not use.
Other important topics for java technical interview :

  • We are covering here -'Java garbage collection interview questions' or 'Java memory interview questions' in d...
  • ' Java database questions ' or ' Database interview questions for java developer ' is covered in this blog. All ent...
  • Java Concurrency interview question - In year 2004 when technology gurus said innovation in Java is gone down and Sun Microsystems [Now Or...
  • 'Java investment bank interview' generally contains 'Java Design Pattern' questions. If you want to be a professional Java ...
  • Java Threading Interview Questions

    'Java thread interview questions' is covered in this topic. This topic is the facto for clearing any investment banking jobs. There are few java interviews where they ask most of questions from threading and concurrency. These topic become synonyms on how much knowledge you have in java. No interviewer takes a chance that developer is not be aware of threading. I will say it is better to do same coding to practice this topic.
      
    Java Concurrency Questions.

    Threading Interview Questions:-
    1. Why we need multi-threaded applications?
      Now a day most of servers are coming with multiple processors. To take benefit of these multi core processing capabilities, we need to run application with multiple processes concurrently. In Java, Thread is one of the way to create these light weight process, which can execute at same time and perform tasks. 
    2. What is synchronization ?
      Synchronization is the capability to control the access of multiple threads to shared resources. Without synchronization, it is possible for one thread to modify a shared variable while another thread is in the process of using or updating same shared variable. This usually leads to significant errors.                                                                               
    3. Different way of creating thread?
      The thread could be implemented by using Runnable interface or by extending the Thread class. The Runnable is more advantageous, when you are going for multiple inheritance.
      a) public class MyThread extends Thread
      b) public class MyThread implements Runnable
    4. What is the difference between Thread.start() & Thread.run() method?
      Thread.start() method (native method) of Thread class actually does the job of running the Thread.run() method in a thread. If we directly call Thread.run() method it will executed in same thread, so does not solve the purpose of creating a new thread.   In this sequence the thread changes state.
         
    5. Why do we need run() & start() methods?
      We need run() & start() method both because JVM needs to create a separate thread which can not be differentiated from a normal method call. So this job is done by start method native implementation which has to be explicitly called.
      Another advantage of having these two methods is we can have any object run as a thread if it implements Runnable interface. This is to avoid Java’s multiple inheritance problems which will make it difficult to inherit another class with Thread.
    6. What is ThreadLocal class?
      - A thread-local variable effectively provides a separate copy of its value for each thread that uses it.
      - ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread
      - In case when multiple threads access a ThreadLocal instance, separate copy of Threadlocal variable is maintained for each thread.
      - Common use is seen in DAO pattern where the DAO class can be singleton but the Database connection can be maintained separately for each thread. (Per Thread Singleton)
      Good article on ThreadLocal: http://www-128.ibm.com/developerworks/java/library/j-threads3.html
      Good example : http://javaboutique.internet.com/tutorials/localdata/
      Multithreading in Swing: http://java.sun.com/developer/JDCTechTips/2003/tt1208.html
      Refer API Docs: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ThreadLocal.html
         
    7. When InvalidMonitorStateException is thrown? Why?
      This exception is thrown when you try to call wait()/notify()/notifyAll() any of these methods for an Object from a point in your program where u are NOT having a lock on that object.(i.e. u r not executing any synchronized block/method of that object and still trying to call wait()/notify()/notifyAll())
            wait(), notify() and notifyAll() all throw IllegalMonitorStateException. since This exception is a subclass of RuntimeException so we r not bound to catch it (although u may if u want to). and being a RuntimeException this exception is not mentioned in the signature of wait(), notify(), notifyAll() methods.
    8. What is the difference between sleep(), suspend() and wait() ?
      Thread.sleep() sends the current thread into the "Not Runnable" state for some amount of time. The thread keeps the monitors it has aquired -- i.e. if the thread is currently in a synchronized block or method no other thread can enter this block or method. If another thread calls t.interrupt() it will wake up the sleeping thread. Note that sleep is a static method, which means that it always affects the current thread (the one that is executing the
      sleep method). A common mistake is to call t.sleep() where t is a different thread; even then, it is the current thread that will sleep, not the t thread.
            t.suspend() is deprecated. Using it is possible to halt a thread other than the current thread. A suspended thread keeps all its monitors and since this state is not interruptable it is deadlock prone.
            object.wait() sends the current thread into the "Not Runnable" state, like sleep(), but with a twist. Wait is called on a object, not a thread; we call this object the "lock object." Before lock.wait() is called, the current thread must synchronize on the lock object; wait() then releases this lock, and adds the thread to the "wait list" associated with the lock. Later, another thread can synchronize on the same lock object and call lock.notify(). This wakes up the original,
      waiting thread. Basically, wait()/notify() is like sleep()/interrupt(), only the active thread does not need a direct pointer to the sleeping thread, but only to the shared lock object.
    9. What happens when I make a static method as synchronized?
      Synchronized static methods have a lock on the class "Class", so when a thread enters a synchronized static method, the class itself gets locked by the thread monitor and no other thread can enter any static synchronized methods on that class. This is unlike instance methods, as multiple threads can access "same synchronized instance methods" at same time for different instances.
    10. Can a thread call a non-synchronized instance method of an Object when a synchronized method is being executed ?
      Yes, a Non synchronized method can always be called without any problem. In fact Java does not do any check for a non-synchronized method. The Lock object check is performed only for synchronized methods/blocks. In case the method is not declared synchronized Jave will call even if you are playing with shared data. So you have to be careful while doing such thing. The decision of declaring a method as synchronized has to be based on critical section access. If your method does not access a critical section (shared resource or data structure) it need not be declared synchronized.
      Below is the example which demonstrates this, The Common class has two methods
      synchronizedMethod1() and method1()
      MyThread class is calling both the methods in separate threads,
        

    package com.learning.thread;
    
    class MyThread extends Thread {
     private int id = 0;
     private Common common;   
     public MyThread(String name, int no, Common object) {  
      super(name);
      common = object;
      id = no;
     
     }
     public void run() {
      System.out.println("Running Thread" + this.getName());
      try {
       if (id == 0) {
        common.synchronizedMethod1();
       } else {
        common.method1();
       }
      } catch (Exception e) {
       e.printStackTrace();
      }
     }
    }
     public class Common {
      public synchronized void synchronizedMethod1() {
       System.out.println("synchronizedMethod1 called");
       try {
        Thread.sleep(1000);
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
       System.out.println("synchronizedMethod1 done");
      }
    
      public void method1() {
       System.out.println("Method 1 called");
       try {
        Thread.sleep(1000);
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
       System.out.println("Method 1 done");
      }
    
      public static void main(String... strings){
       Common c = new Common();
       MyThread t1 = new MyThread("MyThread-1", 0, c);
       MyThread t2 = new MyThread("MyThread-2", 1, c);
       t1.start();
       t2.start(); 
      }
    
     }
    
    
    
    
    OutPut-->
    1.  Running ThreadMyThread-1
    2.  synchronizedMethod1 called
    3.  Running ThreadMyThread-2
    4.  Method 1 called
    5.  synchronizedMethod1 done
    6.  Method 1 done
    This shows that method1() - is called even though the synchronizedMethod1() was in execution.
    11. Can two threads call two different synchronized instance methods of an Object?
    No. If a object has synchronized instance methods then the Object itself is used a lock object for controlling the synchronization. Therefore all other instance methods need to wait until previous method call is completed.
    See the below sample code which demonstrate it very clearly. The Class Common has 2 methods called synchronizedMethod1() and synchronizedMethod2() MyThread class is calling both the methods.
     public class Common {
      public synchronized void synchronizedMethod1() {
       System.out.println("synchronizedMethod1 called");
       try {
        Thread.sleep(1000);
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
       System.out.println("synchronizedMethod1 done");
      }
    
      public synchronized void synchronizedMethod2() {
       System.out.println("synchronizedMethod1 called");
       try {
        Thread.sleep(1000);
       } catch (InterruptedException e) {
        e.printStackTrace();
       }  
     }
    
    12. What is a deadlock?
    Deadlock is a situation where two or more threads are blocked forever, waiting for each other. This may occur when two threads, each having a lock on one resource, attempt to acquire a lock on the other's resource. Each thread would wait indefinitely for the other to release the lock, unless one of the user processes is terminated. In terms of Java API, thread deadlock can occur in following conditions:
    o    When two threads call Thread.join() on each other.
    o    When two threads use nested synchronized blocks to lock two objects and the blocks lock the same objects in different order.

    13. What is Starvation? and What is a Livelock?
    Starvation and livelock are much less common a problem than deadlock, but are still problems that every designer of concurrent software is likely to encounter.
    LiveLock
    Livelock occurs when all threads are blocked, or are otherwise unable to proceed due to unavailability of required resources, and the non-existence of any unblocked thread to make those resources available. In terms of Java API, thread livelock can occur in following conditions:

    •    When all the threads in a program execute Object.wait(0) on an object with zero parameter. The program is live-locked and cannot proceed until one or more threads call Object.notify() or Object.notifyAll() on the relevant objects. Because all the threads are blocked, neither call can be made.
    •     When all the threads in a program are stuck in infinite loops.
    Starvation
    Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.
    Starvation occurs when one thread cannot access the CPU because one or more other threads are monopolizing the CPU.
    In Java, thread starvation can be caused by setting thread priorities inappropriately. A lower-priority thread can be starved by higher-priority threads if the higher-priority threads do not yield control of the CPU from time to time.

    14. How to make sure Thread 1 , 2, 3 can run in sequence?
    We can use join() to run the thread in sequence.
    thread1.join();
    thread2.join();
    thread3.join();
    package com.learning.thread;
    public class Join implements Runnable {
     class çounter {
      private int c = 0;
      public void increment() {
       c++;
      }
      public void decrement() {
       c--;
      }
      public int value() {
       return c;
      }
     }
     @Override
     public void run() {
      for (int x = 1; x <= 5; x++) {
       System.out.println("this is thread "
         + Thread.currentThread().getName());
      }
     }
     public static void main(String[] args) throws Exception {
      Join j1 = new Join();
      Thread t1 = new Thread(j1, "1");
      Thread t2 = new Thread(j1, "2");
      Thread t3 = new Thread(j1, "3");
      t1.start();
      t1.join(0);
      t2.start();
      t2.join();
      t3.start();
     }
    }
    
    output :
    this is thread 1
    this is thread 1
    this is thread 2
    this is thread 2
    this is thread 3
    this is thread 3

     If you do not use join then you will get the result in random order.

    15. What is ThreadGroup and its benefit?
    The ThreadGroup class manages groups of threads for Java applications. A ThreadGroup can contain any number of threads, presumably related in some way such as who created them, what function they perform, or when they should be started and stopped. ThreadGroup provides benefit of assigning similar threads to same group.
           ThreadGroups can contain not only threads but also other ThreadGroups. The top-most thread group in a Java application is the thread group named "main". You can create threads and thread groups in the "main" group. You can also create threads and thread groups in subgroups of "main" and so on. The result is a root-like hierarchy of threads and thread groups.  Below example shows how to get all threads running under current threadGroup.

    class EnumerateTest {
        void listCurrentThreads() {
     ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
     int numThreads;
     Thread listOfThreads[];
    
     numThreads = currentGroup.activeCount();
     listOfThreads = new Thread[numThreads];
     currentGroup.enumerate(listOfThreads);
     for (int i = 0; i < numThreads; i++) {
         System.out.println("Thread #" + i + " = " + listOfThreads[i].getName());
     }
        }
    }
    
    15. Create Producer and Consumer of data using synchronization ?
    class DataHolder {
        private int seq;
        private boolean available = false;
    
        public synchronized int get() {
            while (available == false) {
         try {
               wait();
         } catch (InterruptedException e) {
         }
        }
            available = false;
            notify();
            return seq;
        }
    
        public synchronized void put(int value) {
     while (available == true) {
         try {
                wait();
         } catch (InterruptedException e) {
         }
        }
            seq = value;
            available = true;
            notify();
        }
    }
    

    16. Why Java locks \ object monitors are re-entrant?
    The Java runtime system allows a thread to re-acquire a monitor that it already holds because Java monitors are re-entrant. Re-entrant monitors are important because it eliminates the possibility of a thread deadlocking on a monitor that it already holds.

    Read Java Concurrency for latest updates to create multithreaded applications