Tuesday, May 11, 2010

Thread

You can define and instantiate a thread in one of two ways:


1. Extend java.lang.Thread class.

2. Implement the java.lang.Runnable interface.


Following methods are responsible for creating, starting and pausing threads: Start(), Run(), Yield(), Sleep()

And a job always start from run() method so you always need to write code in run() method.


(1st step) Defining a thread:


By extending Thread class:


1. Extend the Thread Class

2. Override the run() method.


The limitation of this approach is that if you extend Thread class, you can’t extend another class.


Public class MyThread extends Thread {

Public void run() {

//----code goes here

}

Public void run(String s) {

//---- code goes here

}

}


Keep in mind that you are free to overload run() method but you must know that overloaded run(String s) method won’t be called unless you call it.


By Implementing Runnable interface:


Public class MyRunnableThread implements Runnable {

Public void run() {

//--- code goes here

}

}


Note: Implementing Runnable interface gives you a way to extend a class.


(2nd step) Instantiating a thread:


Remember, you always need a Thread instance either you are extending a Thread class or Implement a Runnable interface.


Case 1: If you extends the Thread Class:


MyThread myThreadObj = new MyThread();


Note: in this case, you only need to create your subclass object.


Case 2: If you implement Runnable interface:


MyRunableThread runObj = new MyRunnableThread();

Thread myThreadObj = new Thread (runObj);


Note: In this case, you need to create your subclass object and pass your subclass object to Thread;

here you have to follow two steps.


Note: When you create a thread using no-argument constructor (in case 1), the thread will call its own run() method. But when you use Runnable (in case 2), you need to tell the new thread to use your run() method rather that its own.


There are other overloaded constructor in thread class:


Thread()

Thread(Runnable r)

Thread(Runnable r, String threadName)

Thread(String threadName)

Thread(ThreadGroup tg, Runnable r, String tn)

Thread(ThreadGroup tg, Runnable r)

Thread(ThreadGroup tg, String tn)



Before going ahead, just have a look on transitioning between thread states:


When a thread has been instantiated but not started (start () method has not been invoked), the thread is said to be in “New State”.

At this stage, thread is not yet considered to be alive.


Starting a thread:


myThreadObj.start();


The new state means you have a thread object but you don’t have a true thread. So what happens after you call Start();


- A new thread of execution starts

- Thread moves from new state to Runnable state.

- When thread executes, run() method will run.


Method from java.lang.Thread class:


Public static void sleep(long millseconds) throws InterruptedException

Public static void yield()

Public final void join()

Public final void setPriority(int p)


Method from java.lang.Object class:


Public final void wait()

Public final void notify()

Public final void notifyAll()


Setting a Thread’s priority:


Thread.MIN_PRIORITY = 1

Thread.NORM_PRIORITY = 5

Thread.MAX_PRIORITY = 10


Thread States:


A thread can be only in one of five states


1). New: This is the state the thread is in after the Thread instance has been instantiated, but the start() method has not been invoked on the thread. At this point, the thread is considered not alive.


2). Runnable: A thread first enters the Runnable state when the start()method is invoked and a thread can also return to the Runnable state after either running or coming back from a blocked, waiting, or sleeping state. When the thread is in the Runnable state, it is considered alive.


3). Running: This is the state for which the scheduler chooses a thread from the Runnable pool and where the action is performed.


4). Waiting / Blocked / Sleeping: This is the state where the thread is not eligible to run but still alive and before running again it has to go in Runnable state.


The thread may be waiting because the thread run code causes it to wait. Same for sleeping a thread, run code tells it to sleep for a period of time while a thread may be blocked because it’s actually waiting for a resource like I/O or an object lock.


5). Dead: When run() method completes, a thread moved to Dead state. If you invoke start() method on a dead thread instance, it’ll give a runtime exception (not compile time).


Some more interesting fact about waiting/blocked/sleeping states;


try {

Thread.sleep(2*60*1000); // sleep for 2 minutes.

}catch(InterruptedException ie) { }

using sleep() is the best way to help all threads get a chance to run!


Note: sleep() method throw a checked InterruptedException.


When a thread’s sleep() expires, and it wakes up, does not mean it will return to running state. Remember, when a thread wakes up it simply goes back to the runnable state.

Remember that sleep() is a static method, so one thread can not put another thread to sleep.


Connection between Thread Priorities and Yield:


Note: The scheduler in most JVMs uses preemptive, priority-based scheduling. This does not mean that all JVMs usetime slicing.


yield() is supposed to do is make the currently running thread back to runnable to allow other threads of the same priority to get their turn.


The Join() Method: one thread “join onto the end” of another thread by using Join() method.

It is used when there is a situation that thread B should not be run until thread A has completed its work.


Synchronized: To protect data, you must do two things:

  1. Mark the variables private
  2. Synchronize the code that modifies the variables.


Synchronization and locks: Since there is only one lock per object, if one thread has picked up the lock, no other thread can enter the synchronized code until the lock has been released.


Some Important Notes:


  1. Only methods can be synchronized, not variables
  2. Each object has one lock.
  3. A class can have synchronized and non-synchronized methods.
  4. once a thread acquires the lock on an object, no other thread can enter any of the synchronized methods in that class
  5. If a class has both synchronized and nonsynchronized methods, multiple threads can still access the nonsynchronized methods of the class
  6. If a thread goes to sleep, it takes its locks with it
  7. A thread can acquire more than one lock
  8. the thread is free to call other synchronized methods on the same object, using the lock the thread already has, in this case it acquire only one lock but if it calls other synchronized method of other object then it acquire two locks.
  9. You can synchronize a block of code rather than a method. i.e synchronized(this) { }
  10. Static methods can be synchronized. There is only one copy of the static data you’re trying to protect, so you only need one lock per class to synchronize static methods—a lock for the whole class. i.e public static synchronized void getName() { }


Thead Deadlock: Deadlock occurs when two threads are blocked and waiting for each others’ lock.


wait(), notify(), and notifyAll() must be called from within a synchronized context. A thread can’t invoke a wait or notify method on an object unless it owns that object’s lock.


When the wait() method is invoked on an object, the thread executing that code gives up its lock on the object immediately


when notify() is called, that doesn’t mean the thread gives up its lock at that moment.


NotifyAll():This is especially important if you have threads waiting on one object, but for different reasons, and you want to be sure that the right thread gets notified.


Class Object Class Thread Interface Runnable

Class Object’s Method

Class Thread Method

Interface Runnable

wait()

start()

Run()

notify()

yield()


notifyAll()

sleep()



join()