java-technotes

Sunday, October 11, 2015

Producer consumer problem using wait and notify

We have a shared Queue and two threads called Producer and Consumer. Producer thread puts number into shared queue and Consumer thread consumes numbers from shared bucket. Condition is that once an item is produced, consumer thread has to be notified and similarly after consumption producer thread needs to be notified. This inter thread communication is achieved using wait and notify method. Remember wait and notify method is defined in object class, and they are must be called inside synchronized block.

package concurrency;
import java.util.LinkedList;
import java.util.Queue;
import org.apache.log4j.Logger;

public class InterThreadCommunicationExample {

    public static void main(String args[]) {

        final Queue sharedQ = new LinkedList();

        Thread producer = new Producer(sharedQ);
        Thread consumer = new Consumer(sharedQ);

        producer.start();
        consumer.start();

    }
}

public class Producer extends Thread {
    private static final Logger logger = Logger.getLogger(Producer.class);
    private final Queue sharedQ;

    public Producer(Queue sharedQ) {
        super("Producer");
        this.sharedQ = sharedQ;
    }

    @Override
    public void run() {

        for (int i = 0; i < 4; i++) {

            synchronized (sharedQ) {
                //waiting condition - wait until Queue is not empty
                while (sharedQ.size() >= 1) {
                    try {
                        logger.debug("Queue is full, waiting");
                        sharedQ.wait();
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                logger.debug("producing : " + i);
                sharedQ.add(i);
                sharedQ.notify();
            }
        }
    }
}

public class Consumer extends Thread {
    private static final Logger logger = Logger.getLogger(Consumer.class);
    private final Queue sharedQ;

    public Consumer(Queue sharedQ) {
        super("Consumer");
        this.sharedQ = sharedQ;
    }

    @Override
    public void run() {
        while(true) {

            synchronized (sharedQ) {
                //waiting condition - wait until Queue is not empty
                while (sharedQ.size() == 0) {
                    try {
                        logger.debug("Queue is empty, waiting");
                        sharedQ.wait();
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                int number = sharedQ.poll();
                logger.debug("consuming : " + number );
                sharedQ.notify();
              
                //termination condition
                if(number == 3){break; }
            }
        }
    }
}


Producer Consumer Design Pattern with Blocking Queue

BlockingQueue amazingly simplifies implementation of Producer-Consumer design pattern by providing out of the box support of blocking on put() and take(). Developer doesn't need to write confusing and critical piece of wait-notify code to implement communication. BlockingQuue is an interface and Java 5 provides different implantation like ArrayBlockingQueue and LinkedBlockingQueue , both implement FIFO order or elements, while ArrayLinkedQueue is bounded in nature LinkedBlockingQueue is optionally bounded. here is a complete code example of Producer Consumer pattern with BlockingQueue. Compare it with classic wait notify code, its much simpler and easy to understand.


import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ProducerConsumerPattern {

    public static void main(String args[]){
  
     //Creating shared object
     BlockingQueue sharedQueue = new LinkedBlockingQueue();
 
     //Creating Producer and Consumer Thread
     Thread prodThread = new Thread(new Producer(sharedQueue));
     Thread consThread = new Thread(new Consumer(sharedQueue));

     //Starting producer and Consumer thread
     prodThread.start();
     consThread.start();
    }
 
}

//Producer Class in java
class Producer implements Runnable {

    private final BlockingQueue sharedQueue;

    public Producer(BlockingQueue sharedQueue) {
        this.sharedQueue = sharedQueue;
    }

    @Override
    public void run() {
        for(int i=0; i<10; i++){
            try {
                System.out.println("Produced: " + i);
                sharedQueue.put(i);
            } catch (InterruptedException ex) {
                Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

}

//Consumer Class in Java
class Consumer implements Runnable{

    private final BlockingQueue sharedQueue;

    public Consumer (BlockingQueue sharedQueue) {
        this.sharedQueue = sharedQueue;
    }
  
    @Override
    public void run() {
        while(true){
            try {
                System.out.println("Consumed: "+ sharedQueue.take());
            } catch (InterruptedException ex) {
                Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
  
  
}

Output:
Produced: 0
Produced: 1
Consumed: 0
Produced: 2
Consumed: 1
Produced: 3
Consumed: 2
Produced: 4
Consumed: 3
Produced: 5
Consumed: 4
Produced: 6
Consumed: 5
Produced: 7
Consumed: 6
Produced: 8
Consumed: 7
Produced: 9
Consumed: 8
Consumed: 9

You see Producer Thread  produced number and Consumer thread consumes it in FIFO order because blocking queue allows elements to be accessed in FIFO.


Sorting objects by multiple attributes (Java Multilevel Sorting using Apache Collections Framework)

The best way to do this is by using the ComparatorChain from the Apache Collections Framework.
You have to implement for every attribute a Comparator that you add to the Chain in the order you need. Now you can use the chain like a normal Comparator.


Here is how it looks like in code:

 package org.test.comparator;  
 public class Person {  
      public Person(String name, int age) {  
           this.name = name;  
           this.age = age;  
      }  
      public String name;  
      public Integer age;  
      @Override  
      public String toString() {  
           return "[" + name + "|" + age + "]";  
      }  
 }  

 package org.test.comparator;  
   
 import java.util.ArrayList;  
 import java.util.Collections;  
 import java.util.Comparator;  
 import java.util.List;  
   
 import org.apache.commons.collections.comparators.ComparatorChain;  
   
 public class TestComparatorChain {  
      public static void main(String[] args) {  
           List<Person> persons = new ArrayList<Person>();  
           persons.add(new Person("stan", 31));  
           persons.add(new Person("kyle", 22));  
           persons.add(new Person("stan", 11));  
           persons.add(new Person("kyle", 30));  
             
           Comparator<Person> comparatorName = new Comparator<Person>() {  
                @Override  
                public int compare(Person o1, Person o2) {  
                     return o1.name.compareToIgnoreCase(o2.name);  
                }  
           };  
             
           Comparator<Person> comparatorAge = new Comparator<Person>() {  
                @Override  
                public int compare(Person o1, Person o2) {  
                     return o1.age.compareTo(o2.age);  
                }  
           };  
             
           ComparatorChain chain = new ComparatorChain();  
           chain.addComparator(comparatorName);  
           chain.addComparator(comparatorAge);  
             
           System.out.println(persons);  
             
           Collections.sort(persons, chain);  
             
           System.out.println(persons);  
      }  
 }  

Resulting two lines:
[[stan|31], [kyle|22], [stan|11], [kyle|30]]
[[kyle|22], [kyle|30], [stan|11], [stan|31]]

The commons-collections-3.2.1.jar is with 575 kb quite big if you only want to use one class of it.

Tuesday, June 17, 2014

Demonstrates queue in java

// QueueApp.java
// demonstrates queue
// to run this program: C>java QueueApp ////////////////////////////////////////////////////////////////
class Queue
   {
   private int maxSize;
   private long[] queArray;
   private int front;
   private int rear;
   private int nItems;
//--------------------------------------------------------------
   public Queue(int s)          // constructor
      {
      maxSize = s;
      queArray = new long[maxSize];
      front = 0;
      rear = -1;
      nItems = 0;
      }
//--------------------------------------------------------------
   public void insert(long j)   // put item at rear of queue
      {
      if(rear == maxSize-1)         // deal with wraparound
         rear = -1;
      queArray[++rear] = j;         // increment rear and insert
      nItems++;                     // one more item
      }
//--------------------------------------------------------------
   public long remove()         // take item from front of queue
      {
      long temp = queArray[front++]; // get value and incr front
      if(front == maxSize)           // deal with wraparound
         front = 0;
      nItems--;                      // one less item
      return temp;
      }
//--------------------------------------------------------------
   public long peekFront()      // peek at front of queue
      {
      return queArray[front];
      }
//--------------------------------------------------------------
   public boolean isEmpty()    // true if queue is empty
      {
      return (nItems==0);
      }
//--------------------------------------------------------------
   public boolean isFull()     // true if queue is full
      {
      return (nItems==maxSize);
      }
//--------------------------------------------------------------
   public int size()           // number of items in queue
      {
      return nItems;
      }
//--------------------------------------------------------------
   }  // end class Queue
////////////////////////////////////////////////////////////////
class QueueApp
   {
   public static void main(String[] args)
      {
      Queue theQueue = new Queue(5);  // queue holds 5 items

      theQueue.insert(10);            // insert 4 items
      theQueue.insert(20);
      theQueue.insert(30);
      theQueue.insert(40);

      theQueue.remove();              // remove 3 items
      theQueue.remove();              //    (10, 20, 30)
      theQueue.remove();

      theQueue.insert(50);            // insert 4 more items
      theQueue.insert(60);            //    (wraps around)
      theQueue.insert(70);
      theQueue.insert(80);

      while( !theQueue.isEmpty() )    // remove and display
         {                            //    all items
         long n = theQueue.remove();  // (40, 50, 60, 70, 80)
         System.out.print(n);
         System.out.print(" ");
         }
      System.out.println("");
      }  // end main()
   }  // end class QueueApp
////////////////////////////////////////////////////////////////

Binary Tree in Java "Demonstrates binary tree in Java"

package com.vijay.datastructure;

//demonstrates binary tree
//to run this program: C>java TreeApp

import java.io.*;
import java.util.*;               // for Stack class
////////////////////////////////////////////////////////////////
class Node
{
public int iData;              // data item (key)
public double dData;           // data item
public Node leftChild;         // this node's left child
public Node rightChild;        // this node's right child

public void displayNode()      // display ourself
   {
   System.out.print('{');
   System.out.print(iData);
   System.out.print(", ");
   System.out.print(dData);
   System.out.print("} ");
   }
}  // end class Node
////////////////////////////////////////////////////////////////
class Tree
{
private Node root;             // first node of tree

//-------------------------------------------------------------
public Tree()                  // constructor
   { root = null; }            // no nodes in tree yet
//-------------------------------------------------------------
public Node find(int key)      // find node with given key
   {                           // (assumes non-empty tree)
   Node current = root;               // start at root
   while(current.iData != key)        // while no match,
      {
      if(key < current.iData)         // go left?
         current = current.leftChild;
      else                            // or go right?
         current = current.rightChild;
      if(current == null)             // if no child,
         return null;                 // didn't find it
      }
   return current;                    // found it
   }  // end find()
//-------------------------------------------------------------
public void insert(int id, double dd)
   {
   Node newNode = new Node();    // make new node
   newNode.iData = id;           // insert data
   newNode.dData = dd;
   if(root==null)                // no node in root
      root = newNode;
   else                          // root occupied
      {
      Node current = root;       // start at root
      Node parent;
      while(true)                // (exits internally)
         {
         parent = current;
         if(id < current.iData)  // go left?
            {
            current = current.leftChild;
            if(current == null)  // if end of the line,
               {                 // insert on left
               parent.leftChild = newNode;
               return;
               }
            }  // end if go left
         else                    // or go right?
            {
            current = current.rightChild;
            if(current == null)  // if end of the line
               {                 // insert on right
               parent.rightChild = newNode;
               return;
               }
            }  // end else go right
         }  // end while
      }  // end else not root
   }  // end insert()
//-------------------------------------------------------------
public boolean delete(int key) // delete node with given key
   {                           // (assumes non-empty list)
   Node current = root;
   Node parent = root;
   boolean isLeftChild = true;

   while(current.iData != key)        // search for node
      {
      parent = current;
      if(key < current.iData)         // go left?
         {
         isLeftChild = true;
         current = current.leftChild;
         }
      else                            // or go right?
         {
         isLeftChild = false;
         current = current.rightChild;
         }
      if(current == null)             // end of the line,
         return false;                // didn't find it
      }  // end while
   // found node to delete

   // if no children, simply delete it
   if(current.leftChild==null &&
                                current.rightChild==null)
      {
      if(current == root)             // if root,
         root = null;                 // tree is empty
      else if(isLeftChild)
         parent.leftChild = null;     // disconnect
      else                            // from parent
         parent.rightChild = null;
      }

   // if no right child, replace with left subtree
   else if(current.rightChild==null)
      if(current == root)
         root = current.leftChild;
      else if(isLeftChild)
         parent.leftChild = current.leftChild;
      else
         parent.rightChild = current.leftChild;

   // if no left child, replace with right subtree
   else if(current.leftChild==null)
      if(current == root)
         root = current.rightChild;
      else if(isLeftChild)
         parent.leftChild = current.rightChild;
      else
         parent.rightChild = current.rightChild;

   else  // two children, so replace with inorder successor
      {
      // get successor of node to delete (current)
      Node successor = getSuccessor(current);

      // connect parent of current to successor instead
      if(current == root)
         root = successor;
      else if(isLeftChild)
         parent.leftChild = successor;
      else
         parent.rightChild = successor;

      // connect successor to current's left child
      successor.leftChild = current.leftChild;
      }  // end else two children
   // (successor cannot have a left child)
   return true;                                // success
   }  // end delete()
//-------------------------------------------------------------
// returns node with next-highest value after delNode
// goes to right child, then right child's left descendents
private Node getSuccessor(Node delNode)
   {
   Node successorParent = delNode;
   Node successor = delNode;
   Node current = delNode.rightChild;   // go to right child
   while(current != null)               // until no more
      {                                 // left children,
      successorParent = successor;
      successor = current;
      current = current.leftChild;      // go to left child
      }
                                        // if successor not
   if(successor != delNode.rightChild)  // right child,
      {                                 // make connections
      successorParent.leftChild = successor.rightChild;
      successor.rightChild = delNode.rightChild;
      }
   return successor;
   }
//-------------------------------------------------------------
public void traverse(int traverseType)
   {
   switch(traverseType)
      {
      case 1: System.out.print("\nPreorder traversal: ");
              preOrder(root);
              break;
      case 2: System.out.print("\nInorder traversal:  ");
              inOrder(root);
              break;
      case 3: System.out.print("\nPostorder traversal: ");
              postOrder(root);
              break;
      }
   System.out.println();
   }
//-------------------------------------------------------------
private void preOrder(Node localRoot)
   {
   if(localRoot != null)
      {
      System.out.print(localRoot.iData + " ");
      preOrder(localRoot.leftChild);
      preOrder(localRoot.rightChild);
      }
   }
//-------------------------------------------------------------
private void inOrder(Node localRoot)
   {
   if(localRoot != null)
      {
      inOrder(localRoot.leftChild);
      System.out.print(localRoot.iData + " ");
      inOrder(localRoot.rightChild);
      }
   }
//-------------------------------------------------------------
private void postOrder(Node localRoot)
   {
   if(localRoot != null)
      {
      postOrder(localRoot.leftChild);
      postOrder(localRoot.rightChild);
      System.out.print(localRoot.iData + " ");
      }
   }
//-------------------------------------------------------------
public void displayTree()
   {
   Stack globalStack = new Stack();
   globalStack.push(root);
   int nBlanks = 32;
   boolean isRowEmpty = false;
   System.out.println(
   "......................................................");
   while(isRowEmpty==false)
      {
      Stack localStack = new Stack();
      isRowEmpty = true;

      for(int j=0; j<nBlanks; j++)
         System.out.print(' ');

      while(globalStack.isEmpty()==false)
         {
         Node temp = (Node)globalStack.pop();
         if(temp != null)
            {
            System.out.print(temp.iData);
            localStack.push(temp.leftChild);
            localStack.push(temp.rightChild);

            if(temp.leftChild != null ||
                                temp.rightChild != null)
               isRowEmpty = false;
            }
         else
            {
            System.out.print("--");
            localStack.push(null);
            localStack.push(null);
            }
         for(int j=0; j<nBlanks*2-2; j++)
            System.out.print(' ');
         }  // end while globalStack not empty
      System.out.println();
      nBlanks /= 2;
      while(localStack.isEmpty()==false)
         globalStack.push( localStack.pop() );
      }  // end while isRowEmpty is false
   System.out.println(
   "......................................................");
   }  // end displayTree()
//-------------------------------------------------------------
}  // end class Tree
////////////////////////////////////////////////////////////////
class TreeApp
{
public static void main(String[] args) throws IOException
   {
   int value;
   Tree theTree = new Tree();

   theTree.insert(50, 1.5);
   theTree.insert(25, 1.2);
   theTree.insert(75, 1.7);
   theTree.insert(12, 1.5);
   theTree.insert(37, 1.2);
   theTree.insert(43, 1.7);
   theTree.insert(30, 1.5);
   theTree.insert(33, 1.2);
   theTree.insert(87, 1.7);
   theTree.insert(93, 1.5);
   theTree.insert(97, 1.5);

   while(true)
      {
      System.out.print("Enter first letter of show, ");
      System.out.print("insert, find, delete, or traverse: ");
      int choice = getChar();
      switch(choice)
         {
         case 's':
            theTree.displayTree();
            break;
         case 'i':
            System.out.print("Enter value to insert: ");
            value = getInt();
            theTree.insert(value, value + 0.9);
            break;
         case 'f':
            System.out.print("Enter value to find: ");
            value = getInt();
            Node found = theTree.find(value);
            if(found != null)
               {
               System.out.print("Found: ");
               found.displayNode();
               System.out.print("\n");
               }
            else
               System.out.print("Could not find ");
               System.out.print(value + '\n');
            break;
         case 'd':
            System.out.print("Enter value to delete: ");
            value = getInt();
            boolean didDelete = theTree.delete(value);
            if(didDelete)
               System.out.print("Deleted " + value + '\n');
            else
               System.out.print("Could not delete ");
               System.out.print(value + '\n');
            break;
         case 't':
            System.out.print("Enter type 1, 2 or 3: ");
            value = getInt();
            theTree.traverse(value);
            break;
         default:
            System.out.print("Invalid entry\n");
         }  // end switch
      }  // end while
   }  // end main()
//-------------------------------------------------------------
public static String getString() throws IOException
   {
   InputStreamReader isr = new InputStreamReader(System.in);
   BufferedReader br = new BufferedReader(isr);
   String s = br.readLine();
   return s;
   }
//-------------------------------------------------------------
public static char getChar() throws IOException
   {
   String s = getString();
   return s.charAt(0);
   }
//-------------------------------------------------------------
public static int getInt() throws IOException
   {
   String s = getString();
   return Integer.parseInt(s);
   }
//-------------------------------------------------------------
}  // end class TreeApp
////////////////////////////////////////////////////////////////