Technical blog

April 17, 2009

A simple wait notify example

Filed under: thread — Tags: , — paawak @ 16:21

At times we often need to fetch an object which might take a long time. Our preferred way of doing that, especially when we are on a UI thread, is to spawn a different thread so as to keep the UI responsive (this is just one of the many use cases that I can think of now). But since we need that object to proceed further in the current execution, we have to resort to some sort of wait/notify mechanism. The following code demoes a very simplistic approach using the regular wait()/notify().

package com.swayam.thread.test;
 
/**
 *
 * @author paawak
 *
 */
public class WaitNotifyExample {
 
    private Object lock = new Object();
 
    public WaitNotifyExample() {
 
    }
 
    public void runLongTask() {
 
        Thread job = new Thread(new Runnable() {
 
            public void run() {
 
                System.out.println("Long task started");
 
                try {
 
                    int maxCount = 1000;
                    // int maxCount = Integer.MAX_VALUE;
 
                    // do some long task
                    for (int i = 0; i < maxCount; i++) {
                        System.out.println(i);
                    }
 
                    System.out.println("Long task done.");
 
                } finally {
 
                    System.out.println("About to notify lock...");
 
                    synchronized (lock) {
                        lock.notifyAll();
                    }
 
                    System.out.println("Lock notified");
 
                }
 
            }
        });
 
        // job.setPriority(Thread.MAX_PRIORITY - 2);
 
        System.out.println("Starting a long task...");
        job.start();
 
        System.out
                .println("Pausing normal execution and waiting for long task to finish...");
 
        synchronized (lock) {
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
 
        System.out.println("Resuming normal execution as long task is done.");
 
    }
 
    public static void main(String[] a) {
 
        new WaitNotifyExample().runLongTask();
 
    }
 
}

Note: This is far from fool proof. One case where it will fail is if the long task is over before that lock.wait() is called.

June 1, 2008

Producer/Consumer

Filed under: java, thread — Tags: , — paawak @ 11:29

I have tried to come-up with a thread safe and a non thread safe version of a typical producer/consumer scenario.

 
 
package com.swayam.exp;
 
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
 
/**
 * 
 * @author paawak
 */
public class ProducerConsumerSimulator implements Runnable {
 
    private final int sleepInterval;
    private final List<String> list;
    private final boolean producer;
    private final boolean threadSafe;
 
    public ProducerConsumerSimulator(boolean producer, boolean threadSafe,
            int sleepInterval, List<String> list) {
        this.producer = producer;
        this.sleepInterval = sleepInterval;
        this.list = list;
        this.threadSafe = threadSafe;
    }
 
    public void run() {
 
        while (true) {
 
            try {
                Thread.sleep(sleepInterval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
 
            if (producer) {
 
                produce();
 
                if (threadSafe) {
                    synchronized (list) {
                        System.out.println("Consumer, wake-up!!!");
                        list.notify();
                    }
                }
 
            } else {
 
                if (threadSafe) {
                    synchronized (list) {
                        try {
                            System.out.println("Waiting for producer...");
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
 
                consume();
 
            }
 
        }
 
    }
 
    private void produce() {
 
        Calendar cal = Calendar.getInstance();
 
        String str = "Time Now -- " + cal.get(Calendar.MINUTE) + ":"
                + cal.get(Calendar.SECOND) + ":"
                + cal.get(Calendar.MILLISECOND);
 
        list.add(str);
 
        System.out.println("ADDED:: " + str);
 
    }
 
    private void consume() {
 
        try {
            String str = list.remove(0);
            System.out.println("REMOVED:: " + str);
        } catch (IndexOutOfBoundsException e) {
            e.printStackTrace();
        }
 
    }
 
    /**
     * For testing
     * 
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
 
        int PRODUCER_SLEEP_INTERVAL = 1000;
        int CONSUMER_SLEEP_INTERVAL = 30;
        boolean THREAD_SAFE_EXECUTION = true;
 
        List<String> list = new ArrayList<String>();
        Thread producer = new Thread(new ProducerConsumerSimulator(true,
                THREAD_SAFE_EXECUTION, PRODUCER_SLEEP_INTERVAL, list));
        producer.start();
 
        Thread consumer = new Thread(new ProducerConsumerSimulator(false,
                THREAD_SAFE_EXECUTION, CONSUMER_SLEEP_INTERVAL, list));
        consumer.start();
 
    }
 
}

Run this with

boolean THREAD_SAFE_EXECUTION = true;

and

boolean THREAD_SAFE_EXECUTION = false;

And see the difference yourself :).

Powered by WordPress