Monday, 21 October 2019

Java Multi threading interview questions



What is Polling and what are problems with it?

The process of testing a condition repeatedly till it becomes true is known as polling.
Polling is usually implemented with the help of loops to check whether a particular condition is true or not. If it is true, certain action is taken. 
 in a classic queuing problem where one thread is producing data and other is consuming it.




How Java multi threading tackles this problem?



Java uses three methods, namely, wait(), notify() and notifyAll().
All these methods belong to object class as final so that all classes have them. They must be used within a synchronized block only.
§  wait()-It tells the calling thread to give up the lock and go to sleep until some other thread enters the same monitor and calls notify().
§  notify()-It wakes up one single thread that called wait() on the same object. It should be noted that calling notify() does not actually give up a lock on a resource.
§  notifyAll()-It wakes up all the threads that called wait() on the same object.



Producer Consumer Problem- >


public class threadexample
{
    public static void main(String[] args)
                           throws InterruptedException
    {
        final PC pc = new PC();

        // Create a thread object that calls pc.produce()
        Thread t1 = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    pc.produce();
                }
                catch(InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        });

        // Create another thread object that calls
        // pc.consume()
        Thread t2 = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    pc.consume();
                }
                catch(InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        });

        // Start both threads
        t1.start();
        t2.start();

        // t1 finishes before t2
        t1.join();
        t2.join();
    }

// PC (Produce Consumer) class with produce() and
    // consume() methods.
    public static class PC
    {
        // Prints a string and waits for consume()
        public void produce()throws InterruptedException
        {
            // synchronized block ensures only one thread
            // running at a time.
            synchronized(this)
            {
                System.out.println("producer thread running");

                // releases the lock on shared resource
                wait();

                // and waits till some other method invokes notify().
                System.out.println("Resumed");
            }
        }

        // Sleeps for some time and waits for a key press. After key
        // is pressed, it notifies produce().
        public void consume()throws InterruptedException
        {
            // this makes the produce thread to run first.
            Thread.sleep(1000);
            Scanner s = new Scanner(System.in);

            // synchronized block ensures only one thread
            // running at a time.
            synchronized(this)
            {
                System.out.println("Waiting for return key.");
                s.nextLine();
                System.out.println("Return key pressed");

                // notifies the produce thread that it
                // can wake up.
                notify();

                // Sleep
                Thread.sleep(2000);
            }
        }
    }
}



Java Executer Framework->

here we will understand how java executer framework decouple the thread management and creation from rest of the application


What is Executors in java Executor Framework?

Executors is a factory that provides the methods to return ExecutorService, ScheduledExecutorService, ThreadFactory. Find some method details.

newFixedThreadPool(): It returns the pool with fixed number of size. We need to pass the number of threads to this method. If concurrently task are submitted more than the pool size, then rest of task need to wait in queue. It returns ExecutorService.

newScheduledThreadPool: This also creates a fixed size pool but it can schedule the thread to run after some defined delay. It is useful to schedule the task. It returns ScheduledExecutorService.

newCachedThreadPool(): There is no fixed size of this pool. Thread will be created at run time and if there is no task it will alive for 60 second and then die. For short lived threads this pool works good. It returns ExecutorService.



Thread(main thread)

🔻
1-execute(runnable)
         Execute 

  2- offer()
           work queue
                        Thread pool executer
                           runnable            
                           runnable                   4- take()
                           runnable
                           runnable                   5- run()
⥸3- run()⬎                   
          Worker Threads⟲ run()

Overview of ThreadPools
concurrent programs must run large number of program computations
Allocating a thread per computation doesn't scale without developing enormous processing capability and memory.

There are various ways to organize thread pools-

1- Fixed size pool
    reuse fixed no of threads,additional task will be queued until thread is available

2-Cached
Another module is called cached module ,what they do here they create new thread on demand

So if new work appears rather than quing stuff

create new threads on demand
Thread can be terminated if they are not used for a certain time.


Java Executer Framework overview-




    





Runnable - one way task that does not return any result

Callable- two way task that return a result

Future- future reprasents the results of an asynchronous two way task.











































Scheduler Executer Service-
extents executor service support future or periodic execution of tasks.



What Are the Available Implementations of Executorservice in the Standard Library?


The ExecutorService interface has three standard implementations:
  • ThreadPoolExecutor — for executing tasks using a pool of threads. Once a thread is finished executing the task, it goes back into the pool. If all threads in the pool are busy, then the task has to wait for its turn.
  • ScheduledThreadPoolExecutor allows to schedule task execution instead of running it immediately when a thread is available. It can also schedule tasks with fixed rate or fixed delay.
  • ForkJoinPool is a special ExecutorService for dealing with recursive algorithms tasks. If you use a regular ThreadPoolExecutor for a recursive algorithm, you will quickly find all your threads are busy waiting for the lower levels of recursion to finish. The ForkJoinPool implements the so-called work-stealing algorithm that allows it to use available threads more efficiently.







No comments:

Post a Comment

Note: only a member of this blog may post a comment.