Thread Introduction

A thread is a thread of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently. Every thread has a priority. Threads with higher priority are executed in preference to threads with lower priority. Each thread may or may not also be marked as a daemon. When code running in some thread creates a new Thread object, the new thread has its priority initially set equal to the priority of the creating thread, and is a daemon thread if and only if the creating thread is a daemon.

An application that creates an instance of Thread must provide the code that will run in that thread. There are two ways to do this:

Provide a Runnable object. The Runnable interface defines a single method, run, meant to contain the code executed in the thread. The Runnable object is passed to the Thread constructor, as in the HelloRunnable example:

public class HelloRunnable implements Runnable {

    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new Thread(new HelloRunnable())).start();
    }

}

Subclass Thread. The Thread class itself implements Runnable, though its run method does nothing. An application can subclass Thread, providing its own implementation of run, as in the HelloThread example:

public class HelloThread extends Thread {

    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new HelloThread()).start();
    }

}

Difference between Blocked and waiting state in java Thread.

waiting : java thread will be in this state when it calls wait() or join() method. The thread will remain in WAITING state until any other thread calls notify() or notifyAll(). while Blocked The thread will be in this state when it is notified by other thread but has not got the object lock yet.

waiting : The WAITING thread is waiting for notification from other threads. while Blocked The Blocked thread is waiting for other thread to release the lock.

waiting :The WAITING thread can be interrupted. Blocked The BLOCKED thread can?t be interrupted.

Pausing Execution with Sleep

Thread.sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system.

Two overloaded versions of sleep are provided: one that specifies the sleep time to the millisecond and one that specifies the sleep time to the nanosecond. However, these sleep times are not guaranteed to be precise, because they are limited by the facilities provided by the underlying OS. Also, the sleep period can be terminated by interrupts, as we will see in a later section. In any case, you cannot assume that invoking sleep will suspend the thread for precisely the time period specified.

The SleepThread example uses sleep to print messages at four-second intervals:


public class SleepThread {
    public static void main(String args[])
        throws InterruptedException {
        String info[] = { "Mares eat oats","Does eat oats","Little lambs eat ivy", "A kid will eat ivy too" };

        for (int i = 0; i < info.length; i++) {
            //Pause for 4 seconds
            Thread.sleep(4000);
            //Print a message
            System.out.println(info[i]);
        }
    }
}

Interrupts

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It is up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.

 public void interrupt()

Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.

If the thread is frequently invoking methods that throw InterruptedException, it simply returns from the run method after it catches that exception. For example, suppose the central message loop in the SleepThread example were in the run method of a thread is Runnable object

for (int i = 0; i < info.length; i++) {
    // Pause for 4 seconds
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        // We have been interrupted: no more messages.
        return;
    }
    // Print a message
    System.out.println(info[i]);
}

Many methods that throw InterruptedException, such as sleep, are designed to cancel their current operation and return immediately when an interrupt is received.

What if a thread goes a long time without invoking a method that throws InterruptedException? Then it must periodically invoke Thread.interrupted, which returns true if an interrupt has been received. For example:

for (int i = 0; i < inputs.length; i++) {
    heavyCrunch(inputs[i]);
    if (Thread.interrupted()) {
        // We have been interrupted: no more crunching.
        return;
    }
}

In this simple example, the code simply tests for the interrupt and exits the thread if one has been received. In more complex applications, it might make more sense to throw an InterruptedException:

if (Thread.interrupted()) {
    throw new InterruptedException();
}

Joins

In Thread, join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing, t.join(); causes the current thread to pause execution until it is thread terminates. Overloads of join allow the programmer to specify a waiting period. However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify.

Like sleep, join responds to an interrupt by exiting with an InterruptedException.

Synchronization

Threads communicate primarily by sharing access to fields and the objects reference fields refer to. This form of communication is extremely efficient, but makes two kinds of errors possible: thread interference and memory consistency errors. The tool needed to prevent these errors is synchronization.

  • Thread Interference
  • Memory Consistency Errors
  • Synchronized Methods
  • Implicit Locks and Synchronization
  • Atomic Access
  • Thread Interference

    class CounterThread {
        private int c = 0;
    
        public void incrementThread() {
            c++;
        }
    
        public void decrementThread() {
            c--;
        }
    
        public int valueThread() {
            return c;
        }
    
    }
    

    CounterThread is increment will add 1 to c, and each invocation of decrement will subtract 1 from c. However, if a Counter object is referenced from multiple threads, interference between threads may prevent this from happening as expected.

    Interference happens when two operations, running in different threads, but acting on the same data, interleave. This means that the two operations consist of multiple steps, and the sequences of steps overlap.

    Now we understand , how JVM excute the statement, some times it is overlaping.

    Retrieve the current value of c.

    Increment the retrieved value by 1.

    Store the incremented value back in c.

    Suppose Thread A invokes increment at about the same time Thread B invokes decrement. If the initial value of c is 0, their interleaved actions might follow this sequence:

    Thread A: Retrieve c.
    Thread B: Retrieve c.
    Thread A: Increment retrieved value; result is 1.
    Thread B: Decrement retrieved value; result is -1.
    Thread A: Store result in c; c is now 1.
    Thread B: Store result in c; c is now -1.
    

    Memory Consistency Errors

    In synchronization in thread, Memory consistency errors occur when different threads have inconsistent views of what should be the same data. The causes of memory consistency errors are complex . Fortunately, the programmer does not need a detailed understanding of these causes. All that is needed is a strategy for avoiding them.

    int counter = 0;

    The counter field is shared between two threads, A and B. Suppose thread A increments counter:

    counter++; Then, shortly afterwards, thread B prints out counter:

    System.out.println(counter);

    Synchronized Methods

    The Synchronization in Thread, provides two basic synchronization things: synchronized methods and synchronized statements.

    synchronized keyword

    public class SyncCounter {
        private int c = 0;
    
        public synchronized void increment() { //method synchronized
            c++;
        }
    
        public synchronized void decrement() {
            c--;
        }
    
        public synchronized int value() {
            return c;
        }
    }
    

    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.

    Implicit Locks and Synchronization

    In Thread, Synchronization is internal entity is called intrinsic lock or monitor lock.

    Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object is fields has to acquire the object is intrinsic lock before accessing them, and then release the intrinsic lock when it is 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.

    Locks In Synchronized Methods

    When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method is object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.

    Synchronized Statements

    public void addName(String name) {
        synchronized(this) {
            lastName = name;
            nameCount++;
        }
        nameList.add(name);
    }
    

    Atomic Access

    An atomic action cannot stop in the middle, it either happens completely, or it doesnot happen at all. No side effects of an atomic action are visible until the action is complete.

    there are two actions we can specify that are atomic

  • Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).
  • Reads and writes are atomic for all variables declared volatile (including long and double variables).
  • Thread Liveness

    Thread in concurrent application is ability to execute in a timely manner is known as its liveness

    Deadlock

    Deadlock describes a situation where two or more threads are blocked forever, waiting for each other

    public class Deadlock {
        static class Friend {
            private final String name;
            public Friend(String name) {
                this.name = name;
            }
            public String getName() {
                return this.name;
            }
            public synchronized void bow(Friend bower) {
                System.out.format("%s: %s"
                    + "  has bowed to me!%n", 
                    this.name, bower.getName());
                bower.bowBack(this);
            }
            public synchronized void bowBack(Friend bower) {
                System.out.format("%s: %s"
                    + " has bowed back to me!%n",
                    this.name, bower.getName());
            }
        }
    
        public static void main(String[] args) {
            final Friend alphonse =
                new Friend("Ravi");
            final Friend gaston =
                new Friend("Raju");
            new Thread(new Runnable() {
                public void run() { alphonse.bow(Ravi); }
            }).start();
            new Thread(new Runnable() {
                public void run() { Ravi.bow(alphonse); }
            }).start();
        }
    }
    

    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 is 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.

    Immutable Objects

    An object is considered immutable if its state cannot change after it is constructed.

    how create Immutable object in java

  • Donot provide setter method
  • Make all fields final and static
  • Do not allow class to inheritance in sub class. Simply if final , it is right.
  •  final public class ImmutableColorRGB {
    
        // Values must be between 0 and 255.
        final private int red;
        final private int green;
        final private int blue;
        final private String name;
    
        private void check(int red, int green,  int blue) {
            if (red < 0 || red > 255  || green < 0 || green > 255  || blue < 0 || blue > 255) {
                throw new IllegalArgumentException();
            }
        }
    
        public ImmutableColorRGB(int red, int green,  int blue, String name) {
            check(red, green, blue);
            this.red = red;
            this.green = green;
            this.blue = blue;
            this.name = name;
        }
    
    
        public int getRGB() {
            return ((red << 16) | (green << 8) | blue);
        }
    
        public String getName() {
            return name;
        }
    
        public ImmutableColorRGB invert() {
            return new ImmutableColorRGB(255 - red,255 - green, 255 - blue,"Inverse of " + name);
        }
    }
     

    Thread pooll

    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.

    Thread Executor

    In Thread in java, 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

    Executor Interfaces

    java.util.concurrent package defines three executor interfaces:

    Executor : This interface provides a way of decoupling task submission from the mechanics of how each task will be run, including details of thread use, scheduling, etc. An Executor is normally used instead of explicitly creating threads

    class NetworkService implements Runnable {
       private final ServerSocket serverSocket;
       private final ExecutorService pool;
    
       public NetworkService(int port, int poolSize)
           throws IOException {
         serverSocket = new ServerSocket(port);
         pool = Executors.newFixedThreadPool(poolSize);
       }
    
       public void run() { // run the service
         try {
           for (;;) {
             pool.execute(new Handler(serverSocket.accept()));
           }
         } catch (IOException ex) {
           pool.shutdown();
         }
       }
     }
    
     class Handler implements Runnable {
       private final Socket socket;
       Handler(Socket socket) { this.socket = socket; }
       public void run() {
         // read and service request on socket
       }
     }
    

    ExecutorService: An ExecutorService can be shut down, which will cause it to reject new tasks. Two different methods are provided for shutting down an ExecutorService. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks. Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted. An unused ExecutorService should be shut down to allow reclamation of its resources.

     class NetworkService implements Runnable {
       private final ServerSocket serverSocket;
       private final ExecutorService pool;
    
       public NetworkService(int port, int poolSize)
           throws IOException {
         serverSocket = new ServerSocket(port);
         pool = Executors.newFixedThreadPool(poolSize);
       }
    
       public void run() { // run the service
         try {
           for (;;) {
             pool.execute(new Handler(serverSocket.accept()));
           }
         } catch (IOException ex) {
           pool.shutdown();
         }
       }
     }
    
     class Handler implements Runnable {
       private final Socket socket;
       Handler(Socket socket) { this.socket = socket; }
       public void run() {
         // read and service request on socket
       }
     }
    

    ScheduledExecutorService : An ExecutorService that can schedule commands to run after a given delay, or to execute periodically.

    The schedule methods create tasks with various delays and return a task object that can be used to cancel or check execution. The scheduleAtFixedRate and scheduleWithFixedDelay methods create and execute tasks that run periodically until cancelled

    import static java.util.concurrent.TimeUnit.*;
     class BeeperControl {
       private final ScheduledExecutorService scheduler =
         Executors.newScheduledThreadPool(1);
    
       public void beepForAnHour() {
         final Runnable beeper = new Runnable() {
           public void run() { System.out.println("beep"); }
         };
         final ScheduledFuture beeperHandle =
           scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
         scheduler.schedule(new Runnable() {
           public void run() { beeperHandle.cancel(true); }
         }, 60 * 60, SECONDS);
       }
     }
    

    Lock Object

    A lock is a tool for controlling access to a shared resource by multiple threads. Commonly, a lock provides exclusive access to a shared resource: only one thread at a time can acquire the lock and all access to the shared resource requires that the lock be acquired first. However, some locks may allow concurrent access to a shared resource, such as the read lock of a ReadWriteLock.

    The use of synchronized methods or statements provides access to the implicit monitor lock associated with every object, but forces all lock acquisition and release to occur in a block-structured way: when multiple locks are acquired they must be released in the opposite order, and all locks must be released in the same lexical scope in which they were acquired.

    Lock helps avoid many common programming errors involving locks, there are occasions where you need to work with locks in a more flexible way. For example, some algorithms for traversing concurrently accessed data structures require the use of hand-over-hand or chain locking: you acquire the lock of node A, then node B, then release A and acquire C, then release B and acquire D and so on.

    ReentrantLock : A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it. A thread invoking lock will return, successfully acquiring the lock, when the lock is not owned by another thread.

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.Random;
    
    public class ThreadSafelock {
        static class Friend {
            private final String name;
            private final Lock lock = new ReentrantLock();
    
            public Friend(String name) {
                this.name = name;
            }
    
            public String getName() {
                return this.name;
            }
    
            public boolean impendingThreadBow(Friend bower) {
                Boolean myLock = false;
                Boolean yourLock = false;
                try {
                    myLock = lock.tryLock();
                    yourLock = bower.lock.tryLock();
                } finally {
                    if (! (myLock && yourLock)) {
                        if (myLock) {
                            lock.unlock();
                        }
                        if (yourLock) {
                            bower.lock.unlock();
                        }
                    }
                }
                return myLock && yourLock;
            }
                
            public void bow(Friend bower) {
                if (impendingThreadBow(bower)) {
                    try {
                        System.out.format("%s: %s has"
                            + " bowed to me!%n", 
                            this.name, bower.getName());
                        bower.bowBack(this);
                    } finally {
                        lock.unlock();
                        bower.lock.unlock();
                    }
                } else {
                    System.out.format("%s: %s started"
                        + " to bow to me, but saw that"
                        + " I was already bowing to"
                        + " him.%n",
                        this.name, bower.getName());
                }
            }
    
            public void bowBack(Friend bower) {
                System.out.format("%s: %s has" +
                    " bowed back to me!%n",
                    this.name, bower.getName());
            }
        }
    
        static class BowLoop implements Runnable {
            private Friend bower;
            private Friend bowee;
    
            public BowLoop(Friend bower, Friend bowee) {
                this.bower = bower;
                this.bowee = bowee;
            }
        
            public void run() {
                Random random = new Random();
                for (;;) {
                    try {
                        Thread.sleep(random.nextInt(10));
                    } catch (InterruptedException e) {}
                    bowee.bow(bower);
                }
            }
        }
                
    
        public static void main(String[] args) {
            final Friend raju =
                new Friend("Raju");
            final Friend ravi =
                new Friend("Ravi");
            new Thread(new BowLoop(raju, ravi)).start();
            new Thread(new BowLoop(ravi, raju)).start();
        }
    }
    

    Difference between wait and sleep method in java Thread

    Class ->

  • wait() is a method of Object super class
  • sleep() is method of java Thread class
  • Call On:

  • In wait method, Call on an object; current thread must synchronize on the lock object
  • In sleep method ,Call on a Thread; always currently executing thread
  • Synchronized:

  • In wait method, when synchronized multiple threads access same Object one by one
  • In sleep method, when synchronized multiple threads wait for sleep over of sleeping thread
  • CPU State:

  • In wait method, Thread is still in running mode and uses CPU cycles
  • In sleep method, Thread does not consume any CPU cycles
  • Hold lock:

  • In wait method, release the lock for other objects to have chance to execute.
  • In sleep method, keep lock for at least t times if timeout specified or somebody interrupt
  • Wake-up condition:

  • In wait method, until call notify(), notifyAll() from object, the time of wait() means the least waiting time of the thread.
  • In sleep method, until at least time expire or call interrupt()
  • Example

    package javacodepoint;
    
    public class ThreadWaitAndSleet  implements Runnable {
        private int number = 10;
     
        public void firstMethod() throws Exception {
            synchronized (this) {
                number += 100;
                System.out.println("First Method Number: " + number);
            }
        }
     
        public void secondMethod() throws Exception {
            synchronized (this) {
                Thread.sleep(1000);  // (1)
                this.wait(1000);     // (2)
                number *= 200;
                System.out.println("Second Method Number: " + number);
            }
        }
     
        public void run() {
            try {
                firstMethod();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
        public static void main(String[] args) throws Exception {
            ThreadWaitAndSleet threadWaitAndSleet = new ThreadWaitAndSleet();
            Thread thread = new Thread(threadWaitAndSleet);
            thread.start();
            threadWaitAndSleet.secondMethod();
        }
    }
    
    

    The output with (1): Thread.sleep(1000);

    Second Method Number: 2000
    First Method Number: 2100
    

    The output with (2): this.wait(1000);

    Second Method Number: 2000
    First Method Number: 2100
    

    Important things to Know about Threads

    1) If you start a thread that is already started, it throw error java.lang.IllegalThreadStateException at run time. There will be no compilation errors.

     public class DoubleThreadStart
    {
        public static void main(String[] args)
        {
            Thread t = new Thread();
     
            t.start();
     
            t.start();    //This statement will throw java.lang.IllegalThreadStateException
        }
    }
     

    2) Exception occurs in thread t1. only this thread will be terminated abruptly. Thread t2 will continue to execute it is task.

    package javacodepoint;
    
    public class DoubleThreadStart {
    	 public static void main(String[] args)
    	    {
    	        Thread t1 = new Thread()
    	        {
    	            public void run()
    	            {
    	                String n = null;
    	 
    	                System.out.println(n.length());  //This statement will throw NullPointerException
    	 
    	                System.out.println("Statement will not be executed");
    	            }
    	        };
    	 
    	        Thread t2 = new Thread()
    	        {
    	            public void run()
    	            {
    	                for(int i = 0; i <= 100; i++)
    	                {
    	                    System.out.println(i);
    	                }
    	            }
    	        };
    	 
    	        t1.start();
    	 
    	        t2.start();
    	    }
    
    }
    
    

    output

    Exception in thread "Thread-0" 0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    java.lang.NullPointerException
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    	at JUnit.DoubleThreadStart$1.run(DoubleThreadStart.java:12)
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    
    

    3) In java thread class start() method internally calls run() method. What happens when you call run() method directly?. When you call run() method of a thread directly, calling thread will execute the task defined in the run() method.

    package javacodepoint;
    
    public class DoubleThreadStart {
    	public static void main(String[] args)
    {
        Thread t = new Thread()
        {
            public void run()
            {
                System.out.println(Thread.currentThread().getName());    //Output : main
            }
        };
    
        t.run();
    }
    }
    
    

    4) when multiple threads need to execute same task, then use Runnable interface. If multiple threads need to execute different tasks, then go for Thread class

    How stop Thread in java

    Condition based (flag false) : If we write some condition like boolean flag false, on basis of we can stop the thread. this condition write in run() method and We have defined stopRunning() method.

    package javacodepoint;
    
    public class MainClass {
    	 public static void main(String[] args) 
    	    {
    	        MyThread thread = new MyThread();
    	         
    	        thread.start();
    	         
    	        try
    	        {
    	            Thread.sleep(100);
    	        } 
    	        catch (InterruptedException e) 
    	        {
    	            e.printStackTrace();
    	        }
    	         
    	        //call stopRunning() method whenever you want to stop a thread
    	         
    	        thread.stopRunning();
    	    }   
    
    }
    class MyThread extends Thread
    {
         
        private volatile boolean flag = true;
         
        public void stopRunning()
        {
            flag = false;
        }
         
        @Override
        public void run()
        {
             while (flag)
            {
                System.out.println("I am running....");
            }
             
            System.out.println("Stopped Running....");
        }
    }
    

    output

    
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    Stopped Running....
    
    

    Using interrupt() Method : Whenever you call interrupt() method on a thread, it sets the interrupted status of a thread. This status can be obtained by interrupted() method. This status is used in a while loop to stop a thread.

    class MyThread extends Thread
    {    
        @Override
        public void run()
        {
            while (!Thread.interrupted())
            {
                System.out.println("I am running....");
            }
             
            System.out.println("Stopped Running.....");
        }
    }
     
    public class MainClass 
    {   
        public static void main(String[] args) 
        {
            MyThread thread = new MyThread();
             
            thread.start();
             
            try
            {
                Thread.sleep(100);
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
             
            //interrupting the thread
             
            thread.interrupt();
        }    
    }
    

    output

    
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    I am running....
    Stopped Running....
    
    

    Deadlock In Java

    In Java Thread, Deadlock is a condition which occurs when two or more threads get blocked waiting for each other for an infinite period of time to release the resources(Locks) they hold. Deadlock is the common problem in multi threaded programming which can completely stops the execution of an application. So, extra care need to be taken while writing the multi threaded programs so that deadlock never occurs.

     
     package javacodepoint;
    
    
    	
    	class SharedClass
    	{
    	    synchronized void methodOne(SharedClass s)
    	    {
    	        Thread t = Thread.currentThread();
    	 
    	        System.out.println(t.getName()+"is executing methodOne...");
    	 
    	        System.out.println(t.getName()+"is calling methodTwo...");
    	 
    	        s.methodTwo(this);
    	 
    	        System.out.println(t.getName()+"is finished executing methodOne...");
    	    }
    	 
    	    synchronized void methodTwo(SharedClass s)
    	    {
    	        Thread t = Thread.currentThread();
    	 
    	        System.out.println(t.getName()+"is executing methodTwo...");
    	 
    	        System.out.println(t.getName()+"is calling methodOne...");
    	 
    	        s.methodOne(this);
    	 
    	        System.out.println(t.getName()+"is finished executing methodTwo...");
    	    }
    	}
    	public class DeadLockInJava {
    		public static void main(String[] args)
    	    {
    	        final SharedClass s1 = new SharedClass();
    	 
    	        final SharedClass s2 = new SharedClass();
    	 
    	        Thread t1 = new Thread()
    	        {
    	            public void run()
    	            {
    	                s1.methodOne(s2);
    	            }
    	        };
    	 
    	        Thread t2 = new Thread()
    	        {
    	            @Override
    	            public void run()
    	            {
    	                s2.methodTwo(s1);
    	            }
    	        };
    	 
    	        t1.start();
    	 
    	        t2.start();
    	    }
    	}
    
     
     

    t1 waits for t2 to release the object locked by s2

    t2 waits for t1 to release the object locked by s1

    Difference between notify and notifyAll in Java

    notify() In Java Thread:

    A thread in java calls notify() method on a particular object, only one thread will be notified which is waiting for the lock or monitor of that object.

    The thread choose to notify element in random manner . Notified thread doesnot get the lock of the object immediately.

    Before notification, the java thread will be in WAITING state. Once it is notified, it will move to blocked state. It remains in blocked state until it gets the lock. Once it gets the lock, it moves from BLOCKED state to RUNNING state.

     class SharedResouces
    {
        synchronized void waitMethod()
        {
            Thread t = Thread.currentThread();
             
            System.out.println(t.getName()+" is releasing the lock and going to wait");
             
            try
            {
                wait();
            }
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
             
            System.out.println(t.getName()+" has been notified and acquired the lock back");
        }
         
        synchronized void notifyOneThread()
        {
            Thread t = Thread.currentThread();
             
            notify();
             
            System.out.println(t.getName()+" has notified one thread waiting for this object lock");
        }
    }
     
    public class MainClass 
    {   
        public static void main(String[] args) 
        {
            final SharedResouces s = new SharedResouces();
             
            //Thread t1 will be waiting for lock of object s
             
            Thread t1 = new Thread() 
            {
                @Override
                public void run()
                {
                    s.waitMethod();
                }
            };
             
            t1.start();
             
            //Thread t2 will be waiting for lock of object s
             
            Thread t2 = new Thread() 
            {
                @Override
                public void run()
                {
                    s.waitMethod();
                }
            };
     
            t2.start();
             
            //Thread t3 will be waiting for lock of object s
             
            Thread t3 = new Thread() 
            {
                @Override
                public void run()
                {
                    s.waitMethod();
                }
            };
             
            t3.start();
             
            try
            {
                Thread.sleep(1000);
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
             
            //Thread t4 will notify only one thread which is waiting for lock of object s
             
            Thread t4 = new Thread() 
            {
                @Override
                public void run()
                {
                    s.notifyOneThread();
                }
            };
             
            t4.start(); 
        }    
    }
     

    output

     Thread-1 is releasing the lock and going to wait
    Thread-0 is releasing the lock and going to wait
    Thread-2 is releasing the lock and going to wait
    Thread-3 has notified one thread waiting for this object lock
    Thread-1 has been notified and acquired the lock back
    

    notifyAll() In Java Thread:

    Java thread calls notifyAll() method on a particular object, all threads which are waiting for the lock of that object are notified. All notified threads will move from WAITING state to BLOCKED state. All these threads will get the lock of the object on a priority basis. The thread which gets the lock of the object moves to RUNNING state. The remaining threads will remain in BLOCKED state until they get the object lock.

    package javacodepoint;
    class SharedResouces
    {
        synchronized void waitMethod()
        {
            Thread t = Thread.currentThread();
             
            System.out.println(t.getName()+" is releasing the lock and going to wait");
             
            try
            {
                wait();
            }
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
             
            System.out.println(t.getName()+" has been notified and acquired the lock back");
        }
         
        synchronized void notifyAllThread()
        {
            Thread t = Thread.currentThread();
             
            notifyAll();
             
            System.out.println(t.getName()+" has notified all threads waiting for this object lock");
        }
    }
     
    public class MainClass 
    {   
        public static void main(String[] args) 
        {
            final SharedResouces s = new SharedResouces();
             
            //Thread t1 will be waiting for lock of object s
             
            Thread t1 = new Thread() 
            {
                @Override
                public void run()
                {
                    s.waitMethod();
                }
            };
             
            t1.start();
             
            //Thread t2 will be waiting for lock of object s
             
            Thread t2 = new Thread() 
            {
                @Override
                public void run()
                {
                    s.waitMethod();
                }
            };
     
            t2.start();
             
            //Thread t3 will be waiting for lock of object s
             
            Thread t3 = new Thread() 
            {
                @Override
                public void run()
                {
                    s.waitMethod();
                }
            };
             
            t3.start();
             
            try
            {
                Thread.sleep(1000);
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
             
            //Thread t4 will notify all threads which are waiting for lock of object s
             
            Thread t4 = new Thread() 
            {
                @Override
                public void run()
                {
                    s.notifyAllThread();
                }
            };
             
            t4.start(); 
        }    
    }
    

    output

    
    Thread-0 is releasing the lock and going to wait
    Thread-2 is releasing the lock and going to wait
    Thread-1 is releasing the lock and going to wait
    Thread-3 has notified all threads waiting for this object lock
    Thread-1 has been notified and acquired the lock back
    Thread-2 has been notified and acquired the lock back
    Thread-0 has been notified and acquired the lock back
    

    Link
    Eng. Ravi Kumar Verma

    Simple and dept learning technology is very important part in software development. Same story has been implemented at this site, so learn and implement the inovative things, Thanks

    Ravi Kumar Verma