MaheshT.com

December 12, 2010

Thread, Thread Pool And Thread Executor

Filed under: Java — MaheshT @ 9:18 pm

Implementing Threads  in java
There are the following two ways to implements threads.

1. By extending Thread class

2. By implementing the Runnable interface and overwriting the run method.

Let’s look at both ways of implementing java threads through a code example.

1. By extending Thread Class

public class TestThread extends Thread{

  public void run(){
    System.out.println("Running in Thread");
  }

  public static void main(String [] args){
    TestThread testthread  = new TestThread();
     // Call start method to run thread and NOT run.//
    testthread.start();
  }
}

2. By implementing the Runnable interface.

public class TestThread implements Runnable{

  public TestThread(){
  }

  public void doWork(){
    //create instance of Thread and pass this class as argument.
    Thread worker = new Thread(this);
    worker.start();
  }
  // overwrite run method
  public void run(){
    System.out.println("Running in test Thread");
  }

  public static void main(String [] args){
    TestThread testthread  = new TestThread();
    testthread.doWork();
  }

}

Thread Pool
The creation of a thread takes resources and time.  In a server environment (Web or app server) where you can expect continuous requests for web pages, creating threads for each request and letting it die is a waste of CPU resources. In such environments, you can create a thread pool.

Thread pool is a collection of pre-created threads that work on tasks when it available. If there is no task to finish, threads return to the pool and wait for the next request.

Example of Thread Pool

//Thread pool

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class ThreadPool {

  List<Task> taskList = new ArrayList<Task>();
  List<WorkerThread> workers = new ArrayList<WorkerThread>();
  boolean shutdown = false;

  public ThreadPool(int noOfThreads){
    //add worker to connection pool
    for (int i=0; i <noOfThreads;i++){
      WorkerThread workerThread =new WorkerThread("Worker: "+i );
      workers.add(workerThread);
      workerThread.start();
    }

  }

  public void putTaskForExecution(int numberOfTask){
    synchronized(taskList){
      for (int i =0;i <numberOfTask;i++){
        taskList.add(new Task(i));
      }
      //done adding all tasks, notify all waiting threads.
      taskList.notifyAll();
    }

  }
  public void shutDown(){
    shutdown = true;
    synchronized(taskList){
      taskList.notifyAll();
    }
  }

  class Task {
    int taskNo = 0;

    public Task(int taskNo) {
      this.taskNo = taskNo;
    }

    public void doTask(){
      System.out.println(Thread.currentThread().getName() + " Finished task " +taskNo);
    }

  }

  private class WorkerThread extends Thread {

    public WorkerThread(String name){
      super(name);
    }

    public void run(){
      System.out.println("Starting thread ");
      while (!shutdown || !taskList.isEmpty() ){
        try{
          synchronized(taskList){
            if (!taskList.isEmpty()){
              Task myTask = taskList.remove(0);
              myTask.doTask();
            }else {
              //no task to work on, wait for more work
              taskList.wait();
            }
            //give other treads chance to work on tasks
            Thread.yield();
          }
        }catch(Exception e){
          e.printStackTrace();
        }
      }
      System.out.println("Exiting thread " + this.getName());
    }

  }

  public static void main(String [] args){
    System.out.println("Starting thread server");
    //create threads pool with 10 threds
    ThreadPool threadPool = new ThreadPool(10);
    //add task to thread pool and let it run
    threadPool.putTaskForExecution(100);
    System.out.println("Enter 1 to add more task and 0 exit");
    Scanner sc = new Scanner(System.in);
    while(true){
    int i = sc.nextInt();

      if (i == 1){
        threadPool.putTaskForExecution(100);
      }else if(i == 0 ){
        threadPool.shutDown();
        break;
      }else{
        System.out.println("Invalid Input");
      }
      System.out.println("Enter 1 to add more tasks and 0 exit");
    }
    sc.close();

  }

}

As creating pool and managing treads is a bit complex, in Java 5,  we have ready-to-use classes which creates a pool of threads and manages those for you.
Let’s look at an example of creating a thread pool using Thread Executors.


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExe {

  final List <Task> taskList = new ArrayList<Task>();
  final ExecutorService executor = Executors.newFixedThreadPool(5);
  Runnable active;

  ThreadPoolExe() {

  }

  public void finishWork(){

    while(!taskList.isEmpty()){
      Task task = taskList.remove(0);
      System.out.println("Working on task " + task.taskNo);
      executor.execute(task);

    }
  }

  public void putTaskForExecution(int numberOfTask){

      for (int i =0;i <numberOfTask;i++){
        taskList.add(new Task(i));
      }

  }

  public void shutdown(){
    executor.shutdown();

  }

  private class Task implements Runnable {
    int taskNo = 0;

    public Task(int taskNo) {
      this.taskNo = taskNo;
    }

    public void run (){
      System.out.println(Thread.currentThread().getName() + " Finished task:" +taskNo);
      try{
        Thread.sleep(1000);
      }catch( Exception e){}
    }

  }

    public static void main(String [] args){
      System.out.println("Starting thread server");
      //create threads pool with 10 threds
      ThreadPoolExe threadPoolExe = new ThreadPoolExe();

      //add task to thread pool and let it run
      threadPoolExe.putTaskForExecution(100);
      threadPoolExe.finishWork();
      threadPoolExe.shutdown();

    }

}

Powered by WordPress