Showing posts with label threads. Show all posts
Showing posts with label threads. Show all posts

Saturday, May 25, 2013

Threads II

Here is another example of threads.
Get the code here.

/**
 * An enum with a single value is probably the ultimate singleton.
 * However, it can get real ugly real soon as far as testability is concerned.
 *
 * @author megha birmiwal
 */
public enum StatisticsCollector {
// can override methods in enums like this
//      INFLATED_STATS
//              public int getTimesCalled() {
//                      return count * 10;
//              }
//      },
        STATS;
        private static int count = 0;
        private static double timeSum = 0;
        synchronized public void reportStat(double time) {
                count++;
                timeSum += time;
        }
        public int getTimesCalled() {
                return count;
        }
        public double getAverage() {
                return timeSum / getTimesCalled();
        }
}

/**
 * Reports a given time to the {@link StatisticsCollector}.
 *
 * @author megha birmiwal
 */
public class TimeReporter implements Runnable {
        private final int timeToReport;
        private final int count;
        public TimeReporter(int timeToReport, int count) {
                this.timeToReport = timeToReport;
                this.count = count;
        }
        @Override
        public void run() {
                for (int i = 0; i < count; i++) {
                        StatisticsCollector.STATS.reportStat(timeToReport);
                }
        }
}
public class Main {
        public static void main(String args[]) throws InterruptedException {
                Thread threadX1 = new Thread(new TimeReporter(100, 10000));
                threadX1.start();
                Thread threadX2 = new Thread(new TimeReporter(100, 10000));
                threadX2.start();
                Thread threadY = new Thread(new TimeReporter(200, 10000));
                threadY.start();
                threadX1.join();
                threadX2.join();
                threadY.join();
                int timesCalled = StatisticsCollector.STATS.getTimesCalled();
                double average = StatisticsCollector.STATS.getAverage();
                System.out.println("Total Calls: " + (timesCalled));
                System.out.println("Average Time: " + (average));
        }
}

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());
        }
}