Friday, October 21, 2011

How to Set Name in the Threads Created by ExecutorService

If we create a java.util.concurrent.ExecutorService without any argument, it will use DefaultThreadFactory, which has a pre-defined thread name, e.g. pool-n-thread-. To be able to set a different name for threads created by the ExecutorService, we need to create our own ThreadFactory like the example below.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class MyThreadFactory implements ThreadFactory {

    private final String name;
    private final AtomicInteger integer = new AtomicInteger(1);
    
    public MyThreadFactory(String name) {
        this.name = name;
    }
    
    /** 
     * {@inheritDoc}
     */
    @Override
    public Thread newThread(Runnable r) {
        return new Thread(r, name + integer.getAndIncrement());
    }
    
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(5, 
            new MyThreadFactory("Test"));
        try {
            for (int i = 1; i <= 5; i++) {
                es.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            System.out.println(String.format("[%s] Sleeping for 3 secs",
                                Thread.currentThread().getName()));
                            TimeUnit.SECONDS.sleep(3);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        }
        finally {
            es.shutdown();
            try {
                es.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Tuesday, October 11, 2011

How to Schedule Recurring Tasks in Java

Prior to Java 5, to schedule recurring tasks, we need to use java.util.Timer and java.util.TimerTask.
import java.util.Timer;
import java.util.TimerTask;

public class WithTimerTask {
    
    public static void main(String[] args) {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                System.out.println("Do something");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Timer timer = new Timer();
        timer.schedule(task, 0, 1000);
    }
}
From Java 5 onwards, we can easily replace java.util.Timer and java.util.TimerTask with java.util.concurrent.ScheduledExecutorService.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class WithScheduledExecutorService {

    public static void main(String[] args) {
        ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
        ses.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                System.out.println("Do something");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 0, 1000, TimeUnit.MILLISECONDS);
    }
}
java.util.concurrent.ScheduledExecutorService has more advantages as compared to java.util.TimerTask, such as being able to use a thread pool and not being sensitive to system clock. So whenever possible, use java.util.ScheduledExecutorService as opposed to java.util.TimerTask.

Monday, October 3, 2011

How to Get a Return Value from a Thread in Java

If we need to get a return value from a thread in Java, prior to Java 5, we can do something like this.
public class ReturnValueWithThread {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start();

        // busy doing something.....

        while (!t.isDone()) {
            Thread.yield();
        }
        System.out.println(t.getMessage());
    }
    
    static class MyThread extends Thread {
        private boolean done;
        private String message;
        
        /** 
         * {@inheritDoc}
         */
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            done = true;
            message = "Hello World";
        }
        
        public boolean isDone() {
            return done;
        }
        
        public String getMessage() {
            return message;
        }
    }
}

In Java 5 onwards, this task can be easily achieved by using java.util.concurrent.ExecutorService and java.util.concurrent.Future.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ReturnValueWithExecutor {
    public static void main(String[] args) {
        ExecutorService e = Executors.newFixedThreadPool(1);
        Future<String> f = e.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return "Hello World";
            }
        });

        // busy doing something...

        try {
            String message = f.get();
            System.out.println(message);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        } catch (ExecutionException e1) {
            e1.printStackTrace();
        }
    }
} 

How to Start Threads at the Same Time in Java

Suppose we need to start few threads in Java at the same time, the easy way to do it by using something like below.
public class WithForLoop {

    private static final int NUM_THREADS = 5;

    public static void main(String[] args) {
        for (int i = 0; i < NUM_THREADS; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(String.format(
                        "%s: Do something....",
                        Thread.currentThread().getName()));
                }
            }).start();
        }
    }
}
The problem with it is that we give a head-start for thread 1 to start first. For most cases, it may not matter, but if let's say we need to make sure all the threads get started at the same time, we can make use of java.util.concurrent.CountDownLatch.

import java.util.concurrent.CountDownLatch;

public class WithCountDownLatch {

    private static final int NUM_THREADS = 5;

    public static void main(String[] args) {
        final CountDownLatch startGate = new CountDownLatch(1);
        final CountDownLatch endGate = new CountDownLatch(NUM_THREADS);
        for (int i = 0; i < NUM_THREADS; i++) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        try {
                            startGate.await();
                            System.out.println(String.format(
                                 "%s: Do something....",
                                 Thread.currentThread().getName()));
                        } finally {
                            endGate.countDown();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            t.start();
        }
        
        // this will cause all the threads to get executed concurrently
        startGate.countDown();
        try {
            endGate.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}