-->

Multi threading


Multi threading

Threads A program can be divided into a number of small processes. Each small 

process can be addressed as a single thread.

Multithreading in java is a process of executing multiple threads simultaneously.
In Java, the word thread means two different things.
·         An instance of Thread class.
·         or, A thread of execution.
Advantages of Multi-threading in Java
1.   It allows multiple operations at once, as they are not dependent on each other, thus not blocking the user.
2.   It saves time as multiple operations are possible.
3.   They are independent thus making the functionality better.
Life cycle of threads


  • New : A thread begins its life cycle in the new state. It remains in this state until the start() method is called on it.
  • Runnable : After invocation of start() method on new thread, the thread becomes runnable.
  • Running : A thread is in running state if the thread scheduler has selected it.
  • Waiting : A thread is in waiting state if it waits for another thread to perform a task. In this stage the thread is still alive.
  • Terminated : A thread enter the terminated state when it complete its task.

Commonly used methods of Thread class:

1.   public void run(): is used to perform action for a thread.
2.   public void start(): starts the execution of the thread.JVM calls the run() method on the thread.
3.   public void sleep(long miliseconds): Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds.
4.   public void join(): waits for a thread to die.
5.   public void join(long miliseconds): waits for a thread to die for the specified miliseconds.
6.   public int getPriority(): returns the priority of the thread.
7.   public int setPriority(int priority): changes the priority of the thread.
8.   public String getName(): returns the name of the thread.
9.   public void setName(String name): changes the name of the thread.
10.         public Thread currentThread(): returns the reference of currently executing thread.
11.         public int getId(): returns the id of the thread.
12.         public Thread.State getState(): returns the state of the thread.
13.         public boolean isAlive(): tests if the thread is alive.
14.         public void yield(): causes the currently executing thread object to temporarily pause and allow other threads to execute.
15.         public void suspend(): is used to suspend the thread(depricated).
16.         public void resume(): is used to resume the suspended thread(depricated).
17.         public void stop(): is used to stop the thread(depricated).

Implementing the Runnable Interface

The easiest way to create a thread is to create a class that implements the runnable interface. After implementing runnable interface , the class needs to implement the run() method, which is of form,
public void run()
·         run() method introduces a concurrent thread into your program. This thread will end when run() method terminates.
·         You must specify the code that your thread will execute inside run() method.
·         run() method can call other methods, can use other classes and declare variables just like any other normal method.
class cse implements Runnable{ 
  public void run(){ 
    System.out.println("My thread is in running state."); 
  }  
  public static void main(String args[]){ 
     cse obj=new cse(); 
     Thread T1 =new Thread(obj); 
     T1.start(); 
 } 
}
Output
My thread is in running state.

Creating multi threads using extends
The procedure for creating threads based on extending the Thread is as follows:
1. A class extending the Thread class overrides the run() method from the Thread class to define the code executed by the thread.
2. This subclass may call a Thread constructor explicitly in its constructors to initialize the thread, using the super() call.
3. The start() method inherited from the Thread class is invoked on the object of the class to make the thread eligible for running.
Below is a program that illustrates instantiation and running of threads by extending the Thread class instead of implementing the Runnable interface. To start the thread you need to invoke the start()method on your object.


class bkec extends Thread{  
public void run(){  
System.out.println("BKEC thread ");  
}  
public static void main(String args[]){  
bkec t1=new bkec();  
t1.start();  
 }  
}  

Thread class with sleep() method
class Test extends Thread
{  
 public void run(){  
  for(int i=1;i<5;i++){  
    try
{
Thread.sleep(500);
}catch(InterruptedException e)
{
   System.out.println(e);
}  
    System.out.println(i);  
  }  
 }  
 public static void main(String args[]){  
  Test t1=new Test();  
  Test t2=new Test();  
   
  t1.start();  
  t2.start();  
 }  
}  
Output  1 2 2 3 3 4 4

Synchronization

At times when more than one thread try to access a shared resource, we need to ensure that resource will be used by only one thread at a time. The process by which this is achieved is called synchronization.
1)The synchronized keyword in Java provides locking, which ensures mutually exclusive access to the shared resource and prevents data race.

2) synchronized keyword also prevent reordering of code statement by the compiler which can cause a subtle concurrent issue if we don't use synchronized or volatile keyword.

3) synchronized keyword involve locking and unlocking. before entering into synchronized method or block thread needs to acquire the lock, at this point it reads data from main memory than cache and when it release the lock, it flushes write operation into main memory which eliminates memory inconsistency errors.

Synchronized method
Class Cse
{
  Synchronized void show( string s)
  {   system.out.println(“ hello “ +s);
 
    Try{
               Thread.sleep(500);
              }
Catch(interruptedException e)
 {    system.out.println(“end “+s);
}
}
Class bkec extends threads
{
     Cse c;
      Public bkec(cse c1, string s)
      {
              Super (s);
           c =c1;
         star();
}
} 
       Public void run( )
{
      c.show(Thread.CurrentThread( ).getName( ));
}
}

Class bet
{
   Public static void main(string argc[])
{
   Cse c1;
 Bkec b=new bkec(c1, “bkec”);
Bkec b1=new bkec(c1, “cse dept”);
Bkec b2=new bkec(c1, “bet trust”);
}
}

Output
Hello bkec
End   bkec
Hello cse dept
End cse dept
Hello bet trust
End bet trust


Synchronized block
Class Cse
{
  void show( string s)
  {   system.out.println(“ hello “ +s);
 
    Try{
               Thread.sleep(500);
              }
Catch(interruptedException e)
 {    system.out.println(“end “+s);
}
}
Class bkec extends threads
{
     Cse c;
      Public bkec(cse c1, string s)
      {
              Super (s);
           c =c1;
         star();
}
} 
       Public void run( )
{
   Synchronized(c)
{
    c.show(Thread.CurrentThread( ).getName( ));
}
}

Class bet
{
   Public static void main(string argc[])
{
   Cse c1;
 Bkec b=new bkec(c1, “bkec”);
Bkec b1=new bkec(c1, “cse dept”);
Bkec b2=new bkec(c1, “bet trust”);
}
}

Output
Hello bkec
End   bkec
Hello cse dept
End cse dept
Hello bet trust
End bet trust

 

 Producer-Consumer solution using threads in Java

In computing, the producer–consumer problem (also known as the bounded-buffer problem) is a classic example of a multi-process synchronization problem. The problem describes two processes, the producer and the consumer, which share a common, fixed-size buffer used as a queue.
§  The producer’s job is to generate data, put it into the buffer, and start again.
§  At the same time, the consumer is consuming the data (i.e. removing it from the buffer), one piece at a time.
Problem
To make sure that the producer won’t try to add data into the buffer if it’s full and that the consumer won’t try to remove data from an empty buffer.
Solution 
The producer is to either go to sleep or discard data if the buffer is full. The next time the consumer removes an item from the buffer, it notifies the producer, who starts to fill the buffer again. In the same way, the consumer can go to sleep if it finds the buffer to be empty. The next time the producer puts data into the buffer, it wakes up the sleeping consumer.
An inadequate solution could result in a deadlock where both processes are waiting to be awakened.

The Producer/Consumer Example

In this example, the Producer (in a .java source file) generates an integer between 0 and 9 (inclusive), stores it in a CubbyHole (in a .java source file) object. To make the synchronization problem more interesting, the Producer sleeps for a random amount of time between 0 and 100 milliseconds before repeating the number-generating cycle:
public class Producer extends Thread {
    private CubbyHole cubbyhole;
    private int number;
 
    public Producer(CubbyHole c, int number) {
        cubbyhole = c;
        this.number = number;
    }
 
    public void run() {
        for (int i = 0; i < 10; i++) {
            cubbyhole.put(number, i);
            try {
                sleep((int)(Math.random() * 100));
            } catch (InterruptedException e) { }
        }
    }
}
The Consumer (in a .java source file) consumes all integers from the CubbyHole (the exact same object into which the Producer put the integers in the first place) as quickly as they become available.
public class Consumer extends Thread {
    private CubbyHole cubbyhole;
    private int number;
 
    public Consumer(CubbyHole c, int number) {
        cubbyhole = c;
        this.number = number;
    }
 
    public void run() {
        int value = 0;
        for (int i = 0; i < 10; i++) {
            value = cubbyhole.get(number);
        }
    }
}

Bounded Buffer Problem

Bounded buffer problem, which is also called producer consumer problem, is one of the classic problems of synchronization. Let's start by understanding the problem here, before moving on to the solution and program code.


What is the Problem Statement?

There is a buffer of n slots and each slot is capable of storing one unit of data. There are two processes running, namely, producer and consumer, which are operating on the buffer.
Bounded Buffer Problem


A producer tries to insert data into an empty slot of the buffer. A consumer tries to remove data from a filled slot in the buffer. As you might have guessed by now, those two processes won't produce the expected output if they are being executed concurrently.
There needs to be a way to make the producer and consumer work in an independent manner.


Here's a Solution

One solution of this problem is to use semaphores. The semaphores which will be used here are:
·         m, a binary semaphore which is used to acquire and release the lock.
·         empty, a counting semaphore whose initial value is the number of slots in the buffer, since, initially all slots are empty.
·         full, a counting semaphore whose initial value is 0.
At any instant, the current value of empty represents the number of empty slots in the buffer and full represents the number of occupied slots in the buffer.
Next Topics


Exception Handling

Package

Interface

Applet

1 comment:

sunset said...

c programming create an image samples
Create a negative from png image

Post a Comment

Basic structure of c program