Tuesday, November 30, 2010

Parallel Search

Problem:
Write a Java class that allows parallel search in an array of integer. It provides the following static method:
public static int parallelSearch(int[ ] a , int numThreads)
This method creates as many threads as specified by numThreads, divides the array a into that many parts, and gives each thread a part of the array to search for sequentially. If any thread finds x, then it returns an index i such that A [ i ] = x. Otherwise, the method returns -1.
Solution:


package org.zero.concurrent.chap01;

import java.util.Arrays;

public class ParallelSearch {
    private static int index = -1;

    public static int parallelSearch(int search, int[] in, int numThreads) {
        // partition
        int partitionSize = in.length / numThreads;
        Thread[] threads = new Thread[numThreads];
        int end = 0;
        int begin = 0;
        // search
        for (int i = 0; i < numThreads; i++) {
            end = begin + partitionSize;
            if (i == numThreads - 1 || end > in.length) {
                end = in.length;
            }
            Search target = new Search(begin, end, in, search);
            System.out.println(target);
            threads[i] = new Thread(target);
            threads[i].start();
            System.out.println(threads[i].getName());
            begin = end;
        }
        return index;
    }

    public static void main(String[] args) {
        int[] a = new int[100];
        for (int i = 0; i < a.length; i++) {
            a[i] = (int) (Math.random() * 10);
        }
        int parallelSearch = parallelSearch(2, a, 7);
        if (-1 == parallelSearch) {
            System.out.println("not found");
        } else {
            System.out.println("found at: " + parallelSearch);
        }
    }

    private static class Search implements Runnable {
        int begin;
        int end;
        int[] a;
        int x;

        public Search(int begin, int end, int[] a, int x) {
            super();
            if (end < begin) {
                throw new IllegalStateException();
            }
            this.begin = begin;
            this.end = end;
            this.a = a;
            this.x = x;
        }

        @Override
        public void run() {
            for (int i = begin; i < end; i++) {
                if (x == a[i]) {
                    index = i;
                    System.out.println(i + " "
                            + Thread.currentThread().getName());
                    // break;
                }
            }
        }

        @Override
        public String toString() {
            return "Search [a=" + Arrays.toString(a) + ", length=" + a.length
                    + ", begin=" + begin + ", end=" + end + ", x=" + x + "]";
        }

    }
}
P.S: Any suggestion to improve the code is welcome.

Saturday, November 27, 2010

Product Versioning: Embedding packaging information

Almost serendipitously, I discovered the Java Package class today. One must wonder how possibly this is going to make a difference (aka increase their geek quotient or coolness factor). Well the beauty lies in the details.

Problem Statement: You commit your code to the cvs and after going through the complete lifecycle experience your code finally sees the light of the day, much to your chagrin that the users discovered some bug, even after all those unit testing and that pragmatic ranting ;) But, then you are the rock star developer who had already discovered the problem and fixed it :D but how do you know if user is not using some older version of your package???


Solution: You can embed the information in the manifest file at build time which could be read by exploding the jar, simple!! NO, most of your users wouldn't (shouldn't) know it.It would be really nice if you can print this star-studded information at the beginning of the code execution. You can make this as the first line of your log file or may be a separate file which could be used for bug reporting, options are open.. How do you do it?

Step 1: Create an annotation.

package org.zero;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PACKAGE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyVersionAnnotation {

    String version();

    String revision();

    String date();

    String user();

    String url();
}

Step 2: Generate a class package-info.java
@MyVersionAnnotation(date = "2010-11-26", revision = "11", url = "http://onjava.com/pub/a/onjava/2004/04/21/declarative.html?page=3", user = "nitin", version = "123")
package org.zero;

Step 3: Create a class to access this information;



/**
 * This class finds the package info for mypackage and the MyVersionAnnotation
 * information.
 */
public class PackageDemo {
    private static Package myPackage;
    private static MyVersionAnnotation version;

    static {
        myPackage = MyVersionAnnotation.class.getPackage();
        version = myPackage.getAnnotation(MyVersionAnnotation.class);
    }

    /**
     * Get the meta-data for the mypackage package.
     *
     * @return
     */
    static Package getPackage() {
        return myPackage;
    }

    /**
     * Get the mypackage version.
     *
     * @return the mypackage version string, eg. "0.6.3-dev"
     */
    public static String getVersion() {
        return version != null ? version.version() : "Unknown";
    }

    /**
     * Get the subversion revision number for the root directory
     *
     * @return the revision number, eg. "451451"
     */
    public static String getRevision() {
        return version != null ? version.revision() : "Unknown";
    }

    /**
     * The date that mypackage was compiled.
     *
     * @return the compilation date in unix date format
     */
    public static String getDate() {
        return version != null ? version.date() : "Unknown";
    }

    /**
     * The user that compiled mypackage.
     *
     * @return the username of the user
     */
    public static String getUser() {
        return version != null ? version.user() : "Unknown";
    }

    /**
     * Get the subversion URL for the root mypackage directory.
     */
    public static String getUrl() {
        return version != null ? version.url() : "Unknown";
    }

    /**
     * Returns the buildVersion which includes version, revision, user and date.
     */
    public static String getBuildVersion() {
        return PackageDemo.getVersion() + " from " + PackageDemo.getRevision()
                + " by " + PackageDemo.getUser() + " on "
                + PackageDemo.getDate();
    }

    public static void main(String[] args) {
        System.out.println("mypackage " + getVersion());
        System.out.println("Subversion " + getUrl() + " -r " + getRevision());
        System.out.println("Compiled by " + getUser() + " on " + getDate());
    }
}
PS: Source code courtesy org.apache.hadoop.util.VersionInfo