27 May 2013

Threads In Brief(java)

 when you want to concurrent tasks threads are the way in java to do it. Thread is a lightweight process which is part of the process. The threads can share memory but they run on their own stack. Every thread has a lifecycle. It will be in different states throughout its life cycle.

Thread Life Cycle:-




New State:-

when Thread object is created (Thread as=new Thread(new RunnableImpl)) it will be in new state. In this state the thread is not alive. From new state they move to runnable state.

Runnable State:-

From new state it moves to runnable state when start() method is called on the thread. Once the start() method is called on the thread,  the thread moves to runnable state. In this state the thread is ready to run and is waiting for the thread scheduler to give him a chance to run. In this state the thread is alive. when thread scheduler gives the thread a chance to run then it moves to running state.

Running State:-

Once the thread scheduler gives a chance to a thread that is in runnable state to run then it moves to running state. This is state that does some action. In this state the thread starts executing its task, that means it starts executing the threads “run()” method. As long as it is in this state it keeps executing until it dies. From this state thread can move back to runnable state or it moves to blocked state or it moves to dead state.

Blocked state:-

If the static method yield() is invoked on the thread the thread moves from running state to runnable state. If the static method sleep() is invoked on the thread then it moves to blocking state from running state for a certain period of time. If method wait() is called in the synchronized code then also the thread moves from running state to blocked state. If Thread has to wait for some input then also it moves to blocked state from running state. The thread is alive in this state.

Once the threads are out of blocked state they move to runnable state.

Dead State:-

If the thread finishes its execution, that means if it completes the “run()” method then it moves to a dead state. Once the thread is dead that cannot be started again but it can be accessed as a normal java object.

Thread priorities are not guaranteed. we can set the priorities but it is not guaranteed that the the thread scheduler gives high priority thread a chance to run immediately. It can pick up any thread. Thread scheduler is platform dependent. It may use different algorithms like “Round Robin” or “Time Slicing” for implementation.

Important Methods In Thread Class:-

 Thread.sleep(long millis):-

when this static method is called the currently executing thread moves to blocked state, i mean it sleeps for at least the specified amount of time. If this is called inside the synchronized code the thread goes to sleep without releasing the lock. It does not release the lock until it finishes the synchronized code.

Thread.yield():-

when this static method is called the currently executing thread moves to runnable state from running state.

Thread.join():-

The thread which executes “join()” method on another thread object will stop executing until the other thread on which “join()” is called finishes its execution, i mean until it is dead.

Thread.interrupt():-

Sends signal to thread to interrupt execution.

Inter Thread Communication:-

Threads communicate with each other by using the following methods that are declared inside the class “Object”. All these methods can be called only inside the synchronized code. Before calling this methods the thread has to attain intrinsic lock on that particular object.

 wait()
notify()
notifyAll()

wait():-

This causes the thread to move to waiting state(blocked state) until another thread notifies it. The thread releases the lock before it enters to blocked state. Here the thread enters to a pool of waiting threads on that particular object.

notiy():-

When this method is called on a particular object, it wakes up a single thread from the pool of threads waiting on that particular object. Choosing the thread is arbitrary.

notifyAll():-

When this method is called on a particular object, it wakes up all the threads in the pool waiting on that particular object.

Example for Inter communication:-

class Q {
   int n;
   boolean valueSet = false;
   synchronized int get() {
      if(!valueSet)
      try {
         wait();
      } catch(InterruptedException e) {
         System.out.println("InterruptedException caught");
      }
      System.out.println("Got: " + n);
      valueSet = false;
      notify();
      return n;
   }

   synchronized void put(int n) {
      if(valueSet)
      try {
         wait();
      } catch(InterruptedException e) {
         System.out.println("InterruptedException caught");
      }
      this.n = n;
      valueSet = true;
      System.out.println("Put: " + n);
      notify();
   }
}// end of class Q

class Producer implements Runnable {
   Q q;
   Producer(Q q) {
      this.q = q;
      new Thread(this, "Producer").start();
   }

   public void run() {
      int i = 0;
      while(true) {
         q.put(i++);
      }
   }
}

class Consumer implements Runnable {
    Q q;
    Consumer(Q q) {
       this.q = q;
       new Thread(this, "Consumer").start();
    }
    public void run() {
       while(true) {
       q.get();
    }
  }
}
public class PCFixed {

   public static void main(String args[]) {
      Q q = new Q();
      new Producer(q);
      new Consumer(q);
      System.out.println("Press Control-C to stop.");
   }
}

Guarded Blocks:-
 a block begins by polling a condition that must be true before the block can proceed.
For Example:-
public void guardedJoy() {
    // Simple loop guard. Wastes
    // processor time. Don't do this!
    while(!joy) {}
    System.out.println("Joy has been achieved!");
    // some more instructions goes here.
}

In the above the complete method is guarded by a polling condition. It makes sure the method does not get executed until the condition is met. Until some other thread sets the “joy” value to “false” the loop keeps polling. This also can be improved by Inter Thread Communication(wait, notify).

Thread Liveness:-

The notion that your program will not lock up and eventually do something useful is called the liveness property.

There are a number of reasons why a multi-threaded program will fail liveness:

      Deadlock
      Starvation and Live Lock

Deadlock:-

Both the threads wait for each other to release the resource for further processing is called deadlock.
Example:-

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("Alphonse");
        final Friend gaston =  new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}

Deadlocks can be avoided by using Explicit locks which are introduced as part of the “java.util.concurrent.locks” package from java1.5.

Explicit Locks:-

Lock objects work very much like the implicit locks used by synchronized code. As with implicit locks, only one thread can own a Lock object at a time. Lock objects also support a wait/notify mechanism, through their associated Condition objects.

The biggest advantage of Lock objects over implicit locks is their ability to back out of an attempt to acquire a lock. The tryLock method backs out if the lock is not available immediately or before a timeout expires (if specified). The lockInterruptibly method backs out if another thread sends an interrupt before the lock is acquired.

solving deadlock using explicit locks:-

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Random;

public class Safelock {
    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 impendingBow(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 (impendingBow(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 alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new BowLoop(alphonse, gaston)).start();
        new Thread(new BowLoop(gaston, alphonse)).start();
    }
}

Starvation:-

If the currently executing thread keeps on executing synchronized methods on the object and if it does block the other threads waiting for monitor lock on the same object for longer time is called starvation.

 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.

Thread Safety:-

This can be achieved by avoiding thread interference. This can be done by synchronizing methods, synchronizing blocks and Atomic actions.

The java.util.concurrent package includes a number of additions to the Java Collections Framework which can be safely used in concurrent applications.
Post a Comment