Multi Threading , Producer consumer problem in Java


Multi threading is topic which is always fascinating for java developer. I feel its more about practical the theory. So here i wanted to present sample examples which clear understanding for several multi threading concept.

In Theory basically thread which is light weight process.Thread shares mostly same memory space.
I said mostly because there is some space called thread local which is not common to threads & separate for each thread. We create thread whenever we wanted to use multicore of processor although that doesn't mean single core cant use it. In single core context switching works among different running thread.

for example suppose there is website which is showing latest price as well as offer as well as doing order booking all these things can be assigned to different thread to provide parallel processing.



There are 2 ways for creating a thread.

Extend a thread & Implement a Runnable class. Extending a class is little avoided since it closed possibility for extension further for a java class while implementing runnable is more preferable option.

Since in both case we have to override public void run method. Interface which need to impliment only one method can also be done inline via anonymous class like below. Although in java 8 we say these method as functional interface here i will talk about general approach which is applicable to all version of java.


So here below we can simple create a runnable, assign it to a thread instance & can start it as thread.

package com.amit.corejava;

public class AnonymouseRunnable {

public static void main(String[] args) {

Runnable r = new Runnable() {
public void run() {
System.out.println(" anonymouse class implimentaion");
}
};

Thread t1 = new Thread(r);
t1.start();

}

We can also do like in more direct way as below.

Thread t = new thread(new runnable(){
              public void run() {
System.out.println(" anonymouse class implimentaion");
   }
});

   t.start();




Join Method in Thread.

Its a method available in thread class by which coming thread will join thread currently executing thread & will start only after when thread (on which we call join) is completed.


package com.amit.corejava;

public class SampleRunnable implements Runnable {

@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" going to start work under run()");
threadtask();
}

public void threadtask(){
System.out.println(Thread.currentThread().getName()+" just before task method");
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" is having value ="+Thread.currentThread().getName()+i);
}
}

public static void main(String args[]) throws InterruptedException{

SampleRunnable sr = new SampleRunnable();
Thread t1 = new Thread(sr);
Thread t2 = new Thread(sr);
    t1.setName("Thread A");
    t2.setName("Thread B");
    t1.start();
   
    /*uncomment below to see that join will make it work
    like a sequential program if we remove join both thread
    will start work on same time*/
   
    //t1.join();
    t2.start();
   
}
}


Thread Group

Thread group is something which can used to perform group operation on threads belong to one group. operation like suspend etc. below is sample code for same.

package com.amit.corejava;

public class SampleThreadGroup implements Runnable {

@Override
public void run() {
threadtask();
}

public void threadtask(){
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" is having value ="+i);
}
}

public static void main(String args[]) throws InterruptedException{

ThreadGroup threadGroup = new ThreadGroup("Gang Of Threads");

Thread t1 = new Thread(threadGroup,new SampleThreadGroup());
Thread t2 = new Thread(threadGroup,new SampleThreadGroup());
Thread t3 = new Thread(threadGroup,new SampleThreadGroup());
Thread t4 = new Thread(threadGroup,new SampleThreadGroup());
 
    t1.start();
    t2.start();
    t3.start();
    t4.start();
   
    System.out.println(" Name of group of Thread is "+ threadGroup.getName());
    threadGroup.list();
         
   
}
}



Mutual exclusion

mutual exclusion is where we don't want that multiple thread execute same crtical block of code at same time. We dont want to messup with state of object in between. Its like we want operation to be atomic. We use synchronized   method & synchronized  block to achieve the same.

Below is some sample code with comment to understand what is happening & why.



package com.amit.corejava;

public class SynchronizedRunnable implements Runnable {

@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" going to start work under run()");
   try {
threadtask();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


//uncomment below to see if synchronization via synchronized
//block with in method

/*public void threadtask() throws InterruptedException{
System.out.println(Thread.currentThread().getName()+" just before task method");
Thread.sleep(400);
synchronized(this){
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" is having value ="+Thread.currentThread().getName()+i);
}
}
} */



// uncomment below to see if synchronization via method

public synchronized  void threadtask() throws InterruptedException{
System.out.println(Thread.currentThread().getName()+" just before task method");
Thread.sleep(400);
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" is having value ="+Thread.currentThread().getName()+i);
}
}


// uncomment below to see if no synchronization is present

/*public void threadtask() throws InterruptedException{
System.out.println(Thread.currentThread().getName()+" just before task method");
Thread.sleep(100);
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" is having value ="+Thread.currentThread().getName()+i);
}
}*/



public static void main(String args[]) throws InterruptedException{

SynchronizedRunnable synchronizedRunnable = new SynchronizedRunnable();

// Mind below that we are creating thread for same object of runnbale
// synch or lock  need to acquire if thread work on same object same time.

Thread t1 = new Thread(synchronizedRunnable);
Thread t2 = new Thread(synchronizedRunnable);
    t1.setName("Thread A");
    t2.setName("Thread B");
    t1.start();
   // t1.join();
    t2.start();
   
}

}


Inter thread communication

Just after mutual exclusion next big thing comes as inter thread communication. Which happens with three object methods called wait(), notify(),notifyall(). These methods can be called from synchronized context only otherwise they may give illigal monitor state exception.


I have created a sample producer consumer type example to understand about inter thread communication with help of wait & notify.

You can run below code & easily understand about it. I will explain more in detail theory whenever i will get some time.


package com.amit.corejava;

import java.util.LinkedList;
import java.util.Random;

public class ProducerConsumer {

public LinkedList lst = new LinkedList();
public int max = 10;
public Object lock = new Object();

public static void main(String[] args) throws InterruptedException {

ProducerConsumer pc = new ProducerConsumer();

Thread t1 = new Thread(new Runnable() {
public void run() {
try {
pc.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

Thread t2 = new Thread(new Runnable() {
public void run() {
try {
pc.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

t1.start();
t2.start();


}

public void produce() throws InterruptedException {

int lstObject = 0;

while (true) {
synchronized (lock) {
while (lst.size() == max) {
lock.wait();
}
lst.add(lstObject++);
System.out.print("\n Grown List size is: " + lst.size());
Thread.sleep(1000);
lock.notify();
}

}
}

public void consume() throws InterruptedException {

while (true) {
synchronized (lock) {
while (lst.isEmpty()) {
lock.wait();
}

int value = (int) lst.removeFirst();
System.out.println("\n value is: " + value);
System.out.print(" \n reduce List size is: " + lst.size());

Thread.sleep(1000);
lock.notify();
}

}

}

}




Comments

Popular posts from this blog

Conversion from Clob To String in java and Vice versa

Portable Java 8/ JDK8 setup without admin rights