Saturday, May 25, 2013

Threads

Here's an example of threads. Threads can be created by extending the Thread class and overriding the run() method, or implementing a runnable and passing it to the Thread's constructor.
In this example, we implement the Runnable class.
Explicit synchronization/care should be taken to perform thread-unsafe operations. In this case, the access to the ThreadUnsafeCounter is explicity synchronized in CounterIncrementor. Try commenting out the synchronize block and see the results.

Checkout the code here.

public class ThreadUnsafeCounter {

        private int count = 0;

        public int getCount() {
                return count;
        }

        // unsafe when multiple threads try to increment at the same time.
        // ALL callers need to use ensure that they do not call increment at the same
        // time. This may be done using explicit synchronize blocks.
    public void increment() {
                count++;
        }
}
public class ThreadSafeCounter extends ThreadUnsafeCounter {

        // synchronized makes it safe to call increment() in different threads without
        // explicit locking/synchronization. the jvm with assure that only one call of
        // increment() on an instance of ThreadSafeCounter is running at any given time.
        @Override
        synchronized public void increment() {
                super.increment();
        }
}
/**
 * Increments the given counters a given number of times.
 *
 * @author megha
 */
public class CounterIncrementor implements Runnable {

        private final int times;
        private final ThreadSafeCounter safeCounter;
        private final ThreadUnsafeCounter unsafeCounter;

        public CounterIncrementor(ThreadUnsafeCounter unsafeCounter,
                        ThreadSafeCounter safeCounter, int times) {
                this.unsafeCounter = unsafeCounter;
                this.safeCounter = safeCounter;
                this.times = times;
        }

        @Override
        public void run() {
                for(int i = 0; i < times; i++) {
                        safeCounter.increment();
                        // need to run in a synchronized block to ensure that two
                        // parallel calls to increment are never made
                        synchronized (unsafeCounter) {
                                unsafeCounter.increment();
                        }
                }
        }
}
import java.util.ArrayList;
import java.util.List;

public class Main {

        public static void main(String args[]) throws InterruptedException{

                ThreadUnsafeCounter unsafeCounter = new ThreadUnsafeCounter();
                ThreadSafeCounter safeCounter = new ThreadSafeCounter();
                CounterIncrementor incrementor =
                                new CounterIncrementor(unsafeCounter, safeCounter, 10000);

                List<Thread> threads = new ArrayList<Thread>();
                // start lots of parallel threads that increment the counter(s)
                for (int i = 0; i < 100; i++) {
                        Thread thread = new Thread(incrementor);
                        thread.start();
                        threads.add(thread);
                }

                // wait for all threads to finish
                for (Thread thread: threads) {
                        thread.join();
                }

                // count on unsafe counter matches that of safe counter because
                // CounterIncrement increments unsafeCounter in a safe manner
                System.out.println(unsafeCounter.getCount());
                System.out.println(safeCounter.getCount());
        }
}

No comments:

Post a Comment