Home Java Tools Master-java Parallel Processing

Related Tutorials


 
 

Share on Google+Share on Google+

Parallel Processing

Advertisement
Threading concept is very important in Java Programming language. A thread is a sequential path of code execution within a program. And each thread has its own local variables, program counter and lifetime

Threading

     

Introduction:  
Threading concept is very important in Java Programming language. A thread is a sequential path of code execution within a program. And each thread has its own local variables, program counter and lifetime. In single threaded runtime environment, operations are executes sequentially. That means next operation can execute only when the previous one is complete. But a Multithreading term allows more than one thread to be running concurrently with in a program. Sometimes thread can be referred as lightweight processes because in a program they exist in a common memory space and that?s why they can share both data and code. By using threading we can increased the speed of any application.

Parallel Processing:  
Parallel processing simultaneously and concurrently execution of two or more processes of same computer program by using two or more processors. Parallel processing makes a program execution faster because there are more CPUs running it. Parallel processing requires two or more interconnected processors, each of which executes a different portion of task. Parallel processing differs from multitasking, in which a single CPU executes several programs at once.

Multitasking & Multithreading:  
Multitasking allow to execute more than one tasks at the same time, a task being a program. In multitasking only one CPU is involved but it can switches from one program to another program so quickly that's why it gives the appearance of executing all of the programs at the same time. Multitasking allow processes (i.e. programs) to run concurrently on the program. For Example running the spreadsheet program and you are working with word processor also.
 
Multitasking is running heavyweight processes by a single OS.
  
Multithreading is running multiple lightweight processes in a single process/ task or program. For Example, When you used a word processor you performs a many different tasks such as printing, formatting text, spell checking and so on. Multithreaded software treats each process as a separate program.
  

Advantages of multithreading over multitasking: Some advantages of multithreading over multitasking are :

  • Threads share the same address space.
      
  • Context switching between threads is usually less expensive than between processes.
     
  • Cost of communication between threads is relatively low.

Main Thread: When any standalone application is running, it firstly execute the main() method runs in a one thread, called the main thread. If no other threads are created by the main thread, then program terminates when the main() method complete its execution. The main thread creates some other threads called child threads. The main() method execution can finish, but the program will keep running until the all threads have complete its execution.

Thread Creation: In Java, an object of the Thread class can represent a thread. Thread can be implementing by one of two ways:

  • Extending the java.lang.Thread Class
  • Implementing the java.lang.Runnable Interface

Extending the java.lang.Thread Class

For creating a thread a class have to extend the Thread Class. For creating a thread by this procedure you have to follow these steps:

  1. Extend the java.lang.Thread Class.
  2. Override the run() method in the subclass from the Thread class to define the code executed by the thread.
  3. Create an instance of this subclass. This subclass may call a Thread class constructor by subclass constructor.
  4. Invoke the start() method on the instance of the class to make the thread eligible for running.

The following program demonstrates the thread creation way by extending Thread Class:

class MyThread extends Thread{
  MyThread(String s){
    super(s);
    start();
  }
  public void run(){
    for(int i=0;i<10;i++){
      System.out.println("Thread Name  :"+Thread.currentThread().getName());
      try{
        Thread.sleep(100);
      }catch(Exception e){}
    }
  }
}
public class RunThread{
  public static void main(String args[]){
    System.out.println("Thread Name :"+Thread.currentThread().getName());   
    MyThread m1=new MyThread("My Thread 1");
    MyThread m2=new MyThread("My Thread 2");
  }
}

  Output of the Program is :

C:\j2se6\thread>javac RunThread.java

C:\j2se6\thread>java RunThread
Thread Name :main
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2

C:\j2se6\thread>

Implementing the java.lang.Runnable Interface

The procedure for creating threads by implementing the Runnable Interface is as follows:

  1. A Class implements the Runnable Interface, override the run() method  to define the code executed by thread. An object of this class is Runnable Object.
  2. Create an object of Thread Class by passing a Runnable object as argument.
  3. Invoke the start() method on the instance of the Thread class.

The following program demonstrates the thread creation way by implenting the Runnable interface:

class MyThread1 implements Runnable{
  Thread t;
  MyThread1(String s){
    t=new Thread(this,s);
    t.start();
  }
  public void run(){
    for(int i=0;i<10;i++){
      System.out.println("Thread Name  :"+Thread.currentThread().getName());
      try{
        Thread.sleep(100);
      }catch(Exception e){}
    }
  }
}
public class RunableThread{
  public static void main(String args[])  {
    System.out.println("Thread Name :"+Thread.currentThread().getName());   
    MyThread1 m1=new MyThread1("My Thread 1");
    MyThread1 m2=new MyThread1("My Thread 2");
  }
}

Output of the Program is:

C:\j2se6\thread>javac RunableThread.java

C:\j2se6\thread>java RunableThread
Thread Name :main
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2
Thread Name :My Thread 1
Thread Name :My Thread 2

C:\j2se6\thread>

 

Thread Constructors: Several constructors are available for creating new Thread instances.
  

Thread()

Thread(String)  

Thread(Runnable)

Thread(Runnable,String)

Thread(ThreadGroup,String)

Thread(ThreadGroup,Runnable)

Thread(ThreadGroup,Runnable,String)

Thread(ThreadGroup, Runnable, String, long)

  

ThreadGroup? All threads belongs to an instance of the ThreadGroup Class. ThreadGroup is used to represent a group of threads. ThreadGroups are hierarchical: there is only one root ThreadGroup and it contains all other thread and groups and each subgroups can contain other groups and threads. All thread have only one thread group. And all thread groups (except the root thread group) belongs to exactly one parent thread group. Threads can access the only belonging thread group.

When a new ThreadGroup is created, it is added as a member of existing ThreadGroup.
If a thread x in group1, and executes the code:

  ThreadGroup group2=new ThreadGroup(?group2?);

Then the newly formed group2 comes under group1. If you want a parent group other than default then you have to specify the parent group at the time of creation.

  ThreadGroup group2=new ThreadGroup(group2,?group3?);

Then newly formed group3 comes under the group2.

Some important methods are:

  • getName() ? This method is used to retrieve the name of particular group.
       ThreadGroup g=new ThreadGroup(?RoseIndia?);
       String gname=g.getName();

      

  •  getParent() ? This method is used to retrieve the name of parent threadgroup of sub group.
       ThreadGroup group=group3.getParent();
     

  • activeGroupCount() ? This method returns the number of active thread group in a particular thread group and all its subgroups.
       int size=group.activeGroupCount();
      

  • getThreadGroup() ? This method is used to know the thread is belong to which thread group.
       ThreadGroup group=threadx.getThreadGroup();
      

  • activeCount() ? This method returns the number of active threads in a particular thread group and all its subgroups.

Life Cycle of Threads: When you are programming with threads, understanding the life cycle of thread is very valuable. While a thread is alive, it is in one of several states. By invoking start() method, it doesn?t mean that the thread has access to CPU and start executing straight away. Several factors determine how it will proceed.

Different states of threads are-

  1. New state ? After the creations of Thread instance the thread is in this state but before the start() method invocation. At this point, the thread is considered not alive.
     
  2. Runnable (Ready-to-run) state ? A thread start its life from Runnable state. A thread first enters runnable state after the invoking of start() method but a thread can return to this state after either running, waiting, sleeping or coming back from blocked state also. On this state a thread is waiting for a turn on the processor. 
     
  3. Running state ? A thread is in running state that means the thread is currently executing. There are several ways to enter in Runnable state but there is only one way to enter in Running state: the scheduler select a thread from runnable pool.
     
  4. Dead state ? A thread can be considered dead when its run() method completes. If any thread comes on this state that means it cannot ever run again.
     
  5. Non-Runnable state ? A running thread can enter to any non-runnable state, depending on the circumstances. A thread cannot enters directly to the running state from non-runnable state, firstly it goes to runnable state. Some non-runnable states are as follows:
  • Sleeping ? On this state, the thread is still alive but its not runnable, it might be return to runnable state later if a particular event occurs. On this state a thread sleeps for a specified amount of time.
      
       static void sleep(long millisecond) throws InterruptedException
     
  • Waiting for Notification ? A thread waits for notification from another thread. The thread sends back to runnable state after sending notification from another thread.
     
       final void wait(long timeout) throws InterruptedException
       final void wait(long timeout, int nanos) throws InterruptedException
       final void wait() throws InterruptedException

     
  • Blocked on I/O ? The thread waits for completion of blocking operation. A thread can enter on this state because of waiting I/O resource. In that case the thread sends back to runnable state after availability of resources.
     
  • Blocked for joint completion ? The thread can come on this state because of waiting the completion of another thread.
      
  • Blocked for lock acquisition ? The thread can come on this state because of waiting to acquire the lock of an object.
     

       Different Thread States

Some Important Methods:

  • final boolean isAlive() ? This method is used to find out the thread is alive or not.
      
  • static void yield() ? By invoking this method the current thread pause its execution temporarily and allow other threads to execute.
      
  • final void join() throws InterruptedException and final void join(long millisec) throws InterruptedException ? These two methods invoked on a thread will wait and not return until either the thread has completed or it is timed out respectively.
     
  • void interrupt() ? The method interrupt the threads on which it is invoked.
     
  • final void notify() and final void notifyAll() ? Invoking these method on an object wakes up a single thread that is waiting on the lock of this object. That the object lock is not relinquished when the notifying thread invokes the notify() method. The notifying thread relinquishes the lock at its own discretion, and the awakened thread will not be able to run until the notifying thread relinquishes the object lock

  

Thread Priorities: Thread scheduler can use the thread priorities to determine the execution schedule of threads. Thread gets the ready-to-run state according to their priorities. The thread scheduler provides the CPU time to thread of highest priority thread in the ready-to-run state.

Priorities are integer values from 1 (lowest priority given by the constant Thread.MIN_PRIORITY) to 10 (highest priority given by the constant Thread.MAX_PRIORITY). The default priority is 5(Thread.NORM_PRIORITY).  
  

   setPriority() ? This is method is used to set the priority of thread.

   getPriority() ? This method is used to get the priority of thread.

Lock: This term refers to the access granted to a particular thread that can access the shared resources. At any given time, only one thread can hold the lock and thereby have access to the shared resource. Every object in Java has build-in lock that only comes in action when the object has synchronized method code. By associating a shared resource with a Java object and its lock, the object can act as a guard, ensuring synchronized access to the resource. Only one thread at a time can access the shared resource guarded by the object lock.
  
Since there is one lock per object, if one thread has acquired the lock, no other thread can acquire the lock until the lock is not released by first thread. Acquire the lock means the thread currently in synchronized method and released the lock means exits the synchronized method. Remember the following points related to lock and synchronization:

  • Only methods (or blocks) can be synchronized, Classes and variable cannot be.
     
  • Each object has just one lock.
      
  • All methods in a class need not to be synchronized. A class can have both synchronized and non-synchronized methods.
     
  • If two threads wants to execute a synchronized method in a class, and both threads are using the same instance of the class to invoke the method then only one thread can execute the method at a time.
     
  • If a class has both synchronized and non-synchronized methods, multiple threads can still access the class's non-synchronized methods. If you have methods that don't access the data you're trying to protect, then you don't need to synchronize them. Synchronization can cause a hit in some cases (or even deadlock if used incorrectly), so you should be careful not to overuse it.
      
  • If a thread goes to sleep, it holds any locks it has?it doesn't release them.
      
  • A thread can acquire more than one lock. For example, a thread can enter a synchronized method, thus acquiring a lock, and then immediately invoke a synchronized method on a different object, thus acquiring that lock as well. As the stack unwinds, locks are released again.
     
  • You can synchronize a block of code rather than a method.
     
  • Constructors cannot be synchronized

There are two ways to synchronized the execution of code:

  1. Synchronized Methods
     
  2. Synchronized Blocks (Statements)

Synchronized Methods: If any method is specified with the keyword synchronized then this method of an object is only executed by one thread at a time. A any thread want to execute the synchronized method, firstly it has to obtain the objects lock. Acquire the method is simply by calling the method. If the lock is already held by another thread, then calling thread has to wait. 
 
Synchronized methods are useful in those situations where methods can manipulate the state of an object in ways that can corrupt the state if executed concurrently. Stack implementations usually define the two operations push and pop of elements as synchronized, that?s why pushing and popping are mutually exclusive operations. For Example if several threads were sharing a stack, if one thread is popping the element on the stack then another thread would not be able to pushing the element on the stack.
 

The following program demonstrates the synchronized method:

public class SynThread{
  public static void main(String args[]){
    Share s=new Share();
    MyThread m1=new MyThread(s,"Thread1");
    MyThread m2=new MyThread(s,"Thread2");
    MyThread m3=new MyThread(s,"Thread3");
  }
}
class MyThread extends Thread{
  Share s;
  MyThread(Share s,String str){
    super(str);
    this.s=s;
    start();
  }
  public void run(){
    s.doword(Thread.currentThread().getName());
  }
}
class Share{
  public synchronized void doword(String str){
    for(int i=0;i<5;i++){
    System.out.println("Started   :"+str);
    try{
      Thread.sleep(100);
    }catch(Exception e){}
    }
  }
}

Output of the program is:

C:\j2se6\thread>javac SynThread.java

C:\j2se6\thread>java SynThread
Started :Thread1
Started :Thread1
Started :Thread1
Started :Thread1
Started :Thread1
Started :Thread3
Started :Thread3
Started :Thread3
Started :Thread3
Started :Thread3
Started :Thread2
Started :Thread2
Started :Thread2
Started :Thread2
Started :Thread2

C:\j2se6\thread>

Synchronized Blocks (Statements): A synchronized statement is another way to create synchronized code. Synchronized statements must specify the object that provides the intrinsic lock. The synchronized block allows execution of arbitrary code to be synchronized on the lock of an arbitrary object.

General form of synchronized block is:
synchronized (object reference expression)
{
code block..
}

The following program demonstrates the synchronized block:

public class SynStatement{
  public static void main(String args[]){
    Share s=new Share();
    MyThread m1=new MyThread(s,"Thread1");
    MyThread m2=new MyThread(s,"Thread2");
    MyThread m3=new MyThread(s,"Thread3");
  }
}
class MyThread extends Thread{
  Share s;
  MyThread(Share s,String str){
    super(str);
    this.s=s;
    start();
  }
  public void run(){
    s.doword(Thread.currentThread().getName());
  }
}
class Share{
  public void doword(String str){
    synchronized(this){
    for(int i=0;i<5;i++){
    System.out.println("Started   :"+str);
    try{
      Thread.sleep(100);
    }catch(Exception e){}
    }
    }
  }
}

Output of the program is:


C:\j2se6\thread>javac SynStatement.java

C:\j2se6\thread>java SynStatement
Started :Thread1
Started :Thread1
Started :Thread1
Started :Thread1
Started :Thread1
Started :Thread3
Started :Thread3
Started :Thread3
Started :Thread3
Started :Thread3
Started :Thread2
Started :Thread2
Started :Thread2
Started :Thread2
Started :Thread2

C:\j2se6\thread>

Deadlock: A situation where a thread is waiting for an object lock that holds by second thread, and this second thread is waiting for an object lock that holds by first thread, this situation is known as Deadlock.

The following program demonstrates the deadlock situation:

public class DeadDemo{
  public static void main(String args[]){
  String s1="Dead";
  String s2="Lock";
  MyThread1 m=new MyThread1(s1,s2);
  MyThread2 m1=new MyThread2(s1,s2);
  }
}
class MyThread1 extends Thread{
  String s1;
  String s2;
  MyThread1(String s1, String s2){
  this.s1=s1;
  this.s2=s2;
  start();
  }
  public void run(){
    while(true){
    synchronized(s1){
      synchronized(s2){
      System.out.println(s1+s2);    
      }
    }
    }
  }
}
class MyThread2 extends Thread{
  String s1;
  String s2;
  MyThread2(String s1,String s2){
  this.s1=s1;
  this.s2=s2;
  start();
  }
  public void run(){
    while(true){
    synchronized(s2){
      synchronized(s1){
      System.out.println(s2+s1);
      }
    }
    }
  }
}

Output of the program is:

C:\j2se6\thread>javac DeadDemo.java

C:\j2se6\thread>java DeadDemo
DeadLock
DeadLock
DeadLock
DeadLock
DeadLock
DeadLock
DeadLock
DeadLock
LockDead
LockDead
LockDead
LockDead
LockDead
LockDead
LockDead
DeadLock
DeadLock
DeadLock
DeadLock
DeadLock
DeadLock
DeadLock
.........
.........

C:\j2se6\thread>

Daemon Threads: In Java, any thread can be a Daemon thread. Daemon threads are service providers for other threads or objects running in the same process as the daemon thread. Daemon threads are used for background supporting tasks and are only needed while normal threads are executing. If normal threads are not running and remaining threads are daemon threads then the interpreter exits.

   setDaemon(true/false) ? This method is used to specify that a thread is daemon thread.

   public boolean isDaemon() ? This method is used to determine the thread is daemon thread or not.

The following program demonstrates the Daemon Thread:

public class DaemonThread extends Thread {
  public void run() {
    System.out.println("Entering run method");
    try {
      System.out.println("In run Method: currentThread() is"+ 
                          Thread.currentThread());
      while (true) {
        try {
          Thread.sleep(500);
        }
        catch (InterruptedException x) {
        }
        System.out.println("In run method: woke up again");
      }
      
    }
    finally {
      System.out.println("Leaving run Method");
    }
  }
  public static void main(String[] args) {
    System.out.println("Entering main Method");
    DaemonThread t = new DaemonThread();
    t.setDaemon(true);
    t.start();
    try {
      Thread.sleep(3000);
    }
    catch (InterruptedException x) {
    }
    System.out.println("Leaving main method");
  }
}

Output of this program is:

C:\j2se6\thread>javac DaemonThread.java

C:\j2se6\thread>java DaemonThread
Entering main Method
Entering run method
In run Method: currentThread() isThread[Thread-0,5,main]
In run method: woke up again
In run method: woke up again
In run method: woke up again
In run method: woke up again
In run method: woke up again
In run method: woke up again
Leaving main method

C:\j2se6\thread>
Advertisement

If you enjoyed this post then why not add us on Google+? Add us to your Circles



Liked it!  Share this Tutorial


Follow us on Twitter, or add us on Facebook or Google Plus to keep you updated with the recent trends of Java and other open source platforms.

Posted on: April 17, 2011

Related Tutorials

Discuss: Parallel Processing  

Post your Comment


Your Name (*) :
Your Email :
Subject (*):
Your Comment (*):
  Reload Image
 
 
Comments:0
DMCA.com