Showing posts with label Thread. Show all posts

Understanding Thread.join in Java


Thread.join()
Waits for this thread to die.

Thread.join(long millis)
Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.

This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
Thread.join() and Thread.join(long millis) explained with real world example in Image.

Source code (MessageThread.java)
/**
 * Thread that prints message in interval of 4 seconds.
 *
 * @author javaQuery
 * @date 29th August, 2016
 * @Github: https://github.com/javaquery/Examples
 */
public class MessageThread implements Runnable {

    // Display a message, preceded by
    // the name of the current thread
    static void threadMessage(String message) {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n", threadName, message);
    }

    @Override
    public void run() {
        String importantInfo[] = {
            "Mares eat oats",
            "Does eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too"
        };
        try {
            for (int i = 0; i < importantInfo.length; i++) {
                // Pause for 4 seconds
                Thread.sleep(4000);
                // Print a message
                threadMessage(importantInfo[i]);
            }
        } catch (InterruptedException e) {
            threadMessage("I wasn't done!");
        }
    }
}

Source code (ThreadJoinExample.java)
/**
 * Thread join example.
 * @author javaQuery
 * @date 29th August, 2016
 * @Github: https://github.com/javaquery/Examples
 */
public class ThreadJoinExample {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new MessageThread());
        // start MessageThread.
        t.start();
        /**
         * Main Thread (ThreadJoinExample) will wait for 't' to finish 
         * its task in 5 seconds of it will leave.
         */
        t.join(5000);
        
        /**
         * Main Thread (ThreadJoinExample) will wait until 't' finish its task.
         */
        // t.join(); 
        System.out.println("Main Thread left(finish).");
    }
}

Output
Thread-0: Mares eat oats
Main Thread left(finish).
Thread-0: Does eat oats
Thread-0: Little lambs eat ivy
Thread-0: A kid will eat ivy too

Difference between Thread start() and Runnable run()

Lets first understand run() method of Runnable. Consider following code snippet.

Source code (Car.java)
public class Car implements Runnable{

    @Override
    public void run() {
        System.out.println("Run car...");
    }
}
Source code (Cycle.java)
public class Cycle{

    public void run() {
        System.out.println("Run cycle...");
    }
}
public class Test {
    public static void main(String[] args) {
        /* Calling method of class Cycle */
        new Cycle().run();
        /* Calling method of class Car, doesn't matter class implements Runnable */
        new Car().run();
    }
}
There is no difference between new Cycle().run() and new Car().run() even if Car implements Runnable . You are just calling method of class Car.

Runnable in Thread
public class Test {
    public static void main(String[] args) {
        Thread thread = new Thread(new Car());
        /* It'll start new Thread and call run method of Car() in Thread environment */
        thread.start();
    }
}
run method of Car will be executed in separate Thread environment. thread.start() will start new Thread.

Conclusion
- run method of Runnable will be executed as normal method of class.
- start method of Thread starts the new Thread.

Difference between Thread and Runnable in Java

extends Thread vs implements Runnable

Inheritance
Java supports only single Inheritance means you can't extend more than one class. When you extends Thread you lose the opportunity to extend another class.

Implementing Runnable interface gives you window to extend another class.

Extending class
Extending class means you are changing behavior of super class with your implementation. Since you are not changing the behavior of Thread, implement Runnable.

Runnable as Task
Implementing Runnable represents standalone Task and can be executed by simple Thread or Executors.

Runnable means we can reuse the Task, but you can't restart the Thread once it completes.

Executor Interface
Since you can't restart the Thread once it completes, Java designer decided to accept Runnable class in Executor Interface and it gives more control over your Task compare to Thread.

What is the difference between a process and a thread?

Process vs Thread in Java

Image clarifies the difference between Process and Thread. However lets discuss it point by point.

Process
A process has a self-contained execution environment. An instance of program called Process.

  • Each Process has its own address space.
  • Process have to use Inter Process Communication (IPC) resource like pipes and sockets to communicate with other process.
  • New processes require duplication of the parent process.
  • Processes have considerable overhead.
  • Process have their own copy of data segment of the parent process.
  • Process have control over its child processes.
  • Any change in the parent process does not affect child processes.
  • Process is controlled by the operating system.
  • Processes are independent.

Thread
Threads are sometimes called lightweight processes. It runs within the Process.

  • Thread(s) shares the address space of Process that created it.
  • Threads can directly communicate with other Threads of its process.
  • New threads can be created easily.
  • Threads have almost no overhead.
  • Threads have direct access to data segment of its Process.
  • Threads have considerable control over threads of the same process.
  • Any change in main thread (cancellation, priority change, etc...) may affect the behavior of the other threads of the process.
  • Threads are controlled by programmer in a program.
  • Threads are dependent.

Producer - Consumer Problem in Java


What is Producer - Consumer Problem?
In Simple term we can say, when two Process trying to access same(commonly shared) resource at the same time and one failed to do its operation because another process is using that resource.

In this article we'll generate the Producer - Consumer problem using threads that are trying to access common resource. One thread that is adding/removing records to the List<Integer> and another thread trying to print the records of List<Integer> one-by-one.


Source Code(Problem Generation)
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ProducerConsumerExample {

   /* Create common List of Integer. */
   private static List<Integer> listIntegers = new ArrayList<Integer>();
 
   public static void main(String[] args) {
      /* Start Producer Thread */
      new ProducerThread().start();
      /* Start Consumer Thread */
      new ConsumerThread().start();
   }
 
   /* Producer thread that will add/remove records to `listIntegers` */
   public static class ProducerThread extends Thread{
  
      @Override
      public void run() {
         int index = 0; 
         while(true){
            try {
               /* Put thread in sleep for `1 milliseconds` */
               Thread.sleep(1);
            } catch (Exception e) {
               e.printStackTrace();
            }
    
            if(listIntegers.size() < 100){
               /* Add record to List */
               listIntegers.add(index);
               /* Print the records of List */
               System.out.println("Producer Thread: \n" + listIntegers);
               index++;
            }else{
               /* Remove 1st element from List */
               listIntegers.remove(0);
            }
         }
      }
   }

   /* Consumer thread that will iterate records of `listIntegers` */
   public static class ConsumerThread extends Thread{
  
      @Override
      public void run() {
         while(true){
            try {
               /* Put thread in sleep for `1 milliseconds` */
               Thread.sleep(1);
            } catch (Exception e) {
               e.printStackTrace();
            }
            System.out.println("Consumer Thread iterator list: ");
            /* Get iterator of List */
            Iterator<Integer> iterator = listIntegers.iterator();
            /* Iterate List until last element */
            while(iterator.hasNext()){
               /* Print the element */
               System.out.print(iterator.next() + ", ");
               if(!iterator.hasNext()){
                  System.out.println("");
               }
            }
         }
      }
   }
}
When you run the above program it'll throw an exception java.util.ConcurrentModificationException as shown in following output.

Note: When you execute this program in your system you won't get same output. It depends upon the execution of Thread in your system.

Output 
As you can see clearly portion marked within =. Consumer Thread Iterating the List<Integer> and printed 0 and at the same time Producer Thread added record and Consumer Thread thrown an exception.
/* Removed few lines from output. It printed data of list from 0 to 3 */
Producer Thread: 
[0, 1, 2, 3, 4]
Consumer Thread iterator list: 
0, 1, 2, 3, 4, 
Producer Thread: 
[0, 1, 2, 3, 4, 5]
==========================================
Consumer Thread iterator list: 
0, Producer Thread: 
[0, 1, 2, 3, 4, 5, 6]
Exception in thread "Thread-1" Producer Thread: 
[0, 1, 2, 3, 4, 5, 6, 7]
java.util.ConcurrentModificationException
 at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
 at java.util.ArrayList$Itr.next(Unknown Source)
 at javaQuery.thread.ProducerConsumerExample$ConsumerThread.run(ProducerConsumerExample.java:51)
==========================================


Solution


We can solve this problem using synchronized keyword. synchronized takes care for accessing List<Integer>, while one thread is accessing the List<Integer> another thread has to wait until first thread finishes its work.

Source Code(Solving Problem)
Following program will not give java.util.ConcurrentModificationException exception.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ProducerConsumerExample {

   /* Create common List of Integer. */
   private static List<Integer> listIntegers = new ArrayList<Integer>();
 
   public static void main(String[] args) {
      /* Start Producer Thread */
      new ProducerThread().start();
      /* Start Consumer Thread */
      new ConsumerThread().start();
   }
 
   /* Producer thread that will add/remove records to `listIntegers` */
   public static class ProducerThread extends Thread{
  
      @Override
      public void run() {
         int index = 0;  
         while(true){
            try {
               /* Put thread in sleep for `1 milliseconds` */
               Thread.sleep(1);
            } catch (Exception e) {
               e.printStackTrace();
            }
    
            /* synchronized block */
            synchronized (listIntegers) {
               if(listIntegers.size() < 100){
                  /* Add record to List */
                  listIntegers.add(index);
                  /* Print the records of List */
                  System.out.println("Producer Thread: \n" + listIntegers);
                  index++;
               }else{
                  /* Remove 1st element from List */
                  listIntegers.remove(0);
               }
            }
         }
      }
   }

   /* Consumer thread that will iterate records of `listIntegers` */
   public static class ConsumerThread extends Thread{
  
      @Override
      public void run() {
         while(true){
            try {
               /* Put thread in sleep for `1 milliseconds` */
               Thread.sleep(1);
            } catch (Exception e) {
               e.printStackTrace();
            }
            System.out.println("Consumer Thread iterator list: ");
    
            /* synchronized block */
            synchronized (listIntegers) {
               /* Get iterator of List */
               Iterator<Integer> iterator = listIntegers.iterator();
               /* Iterate List until last element */
               while(iterator.hasNext()){
                  /* Print the element */
                  System.out.print(iterator.next() + ", ");
                  if(!iterator.hasNext()){
                     System.out.println("");
                  }
               }
            }
         }
      }
   }
}