7/7/10

Thread pools , an example

Team, Greetings to you. 

I would like to continue with my previous mail. We heard about thread pools and usages. Now i would like to share one simple example of this concept. 
      
Class PrintTask  implements Runnable , so that each PrintTask object can execute concurrently. Variable sleepTime stores a random integer value  chosen when the PrintTask constructor executes. Each thread running a PrintTask object sleeps for the amount of time specified by the corresponding PrintTask object’s sleepTime, then outputs its name.

package jexample;

/**
 *
 * @author Raghuram
 */
import java.util.Random;

class PrintTask implements Runnable {

    private int sleepTime;
    private String threadName;
    private static Random generator = new Random();


    public PrintTask(String name) {
        threadName = name;

        // pick random sleep time between 0 and 5 seconds
        sleepTime = generator.nextInt(5000);
    }


    public void run() {
        try // put thread to sleep for sleepTime amount of time
        {
            System.out.println("threadName --> "+threadName+" -- sleepTime -- >"+sleepTime);
                    Thread.sleep(sleepTime); // put thread to sleep
        }
        // if thread interrupted while sleeping, print stack trace
        catch (InterruptedException exception) {
            exception.printStackTrace();
        }

        // print thread name
        System.out.println(" done sleeping --->"+ threadName);
    }
    }

The following code is the Thread Executor class . 

creates three threads of execution using the PrintTask class. Method main creates and names three PrintTask objects . Then creating a new ExecutorService. This line uses the newFixedThreadPool method of class Executors, which creates a pool consisting of a fixed number of Threads as indicated by the method’s argument (in this case, 3). These Threads are used by threadExecutor to execute the Runnables. If method execute is called and all the threads in the ExecutorService are being used, the Runnable will be placed in a queue and assigned to the first thread that completes its previous task. Executors method newCachedThreadPool returns an ExecutorService that creates new threads as they are needed by the application.

package jexample;

/**
 *
 * @author Raghuram
 */
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

public class RunnableTester {

    public static void main(String[] args) {
        // create and name each runnable
        
        PrintTask task1 = new PrintTask("thread1");
        PrintTask task2 = new PrintTask("thread2");
        PrintTask task3 = new PrintTask("thread3");
        PrintTask task4 = new PrintTask("thread - extra");
        PrintTask task5 = new PrintTask("thread - extra - 1");
        PrintTask task6 = new PrintTask("thread - extra - 2");

        System.out.println("Starting threads");

        // create ExecutorService to manage threads and see the magic
        
        ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
        // remember the thread pool size is only 3
        
        // start threads and place in runnable state
        threadExecutor.execute(task1); // start task1
        threadExecutor.execute(task2); // start task2
        threadExecutor.execute(task3); // start task3
        threadExecutor.execute(task4); // start task4
        threadExecutor.execute(task5); // start task5
        threadExecutor.execute(task6); // start task6
        threadExecutor.shutdown(); // shutdown worker threads

        System.out.println("Threads started, main ends\n");
    } 

Output will be something similar to the following 
Starting threads
threadName --> thread1 -- sleepTime -- >1530
Threads started, main ends

threadName --> thread2 -- sleepTime -- >1474
threadName --> thread3 -- sleepTime -- >310
 done sleeping --->thread3
threadName --> thread - extra -- sleepTime -- >3189
 done sleeping --->thread2
threadName --> thread - extra - 1 -- sleepTime -- >2148
 done sleeping --->thread1
threadName --> thread - extra - 2 -- sleepTime -- >1295
 done sleeping --->thread - extra - 2
 done sleeping --->thread - extra
 done sleeping --->thread - extra - 1

ExecutorService’s execute method creates a new Thread inside the ExecutorService to run the Runnable passed to it as an argument (in this case a PrintTask) and transitions that Thread from the new state to the runnable state. Method execute returns immediately from each invocation—the program does not wait for each PrintTask to finish. Then ExecutorService method shutdown is called, which will end each Thread in threadExecutor as soon as each finishes executing its Runnable. This program executes only three Runnables, so a new Thread will be created by the ExecutorService for each Runnable. If the program executed more than three Runnables, additional Threads would not be created, but rather an existing Thread would be reused when it completed the Runnable assigned to it.

The code in method main executes in the main thread. This thread is created by the JVM and executes the main method. The code in the run method of PrintTask executes in the threads created by the ExecutorService. When method main terminates  the program itself continues running because there are still threads that are alive i.e., the threads started by threadExecutor that have not yet reached the terminated state. The program will not terminate until its last thread completes execution.

No comments:

Post a Comment

Popular Posts