Saturday, February 2, 2013

Thread pool example using Java and ExecutorService...

Using thread pools is something that is very easy to implement using Java's ExecutorService. The Java ExecutorService class allows you to specify the number of asynchronous tasks that you want to process. Here is an example of an ExecutorService class being instantiated where numThreads is an integer specifying the number of threads to create for the thread pool:
ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
You pass a runnable in the ExecutorService's execute method like this:
executorService.execute(someRunnableObject);
I created a sample method that uses an ExecutorService to similute working on text files. It will move files from the source path to an archive path unless there is a "lock" file found. The "lock" file is an empty file that is named identically to one of the files that is being "worked" on. The lock file is used to ensure that the same file isn't attempted to be worked on by multiple threads. I made this sample because I figured this might be a nice way to handle indexing data in csv files to a Solr server. Here is the method that does the work (which would be very poorly named if it weren't sample code):
public static void DoWorkOnFiles(String sourcePath, String archivePath, int numThreads) throws IOException {

    Random random = new Random();
    ExecutorService executorService = Executors.newFixedThreadPool(numThreads);

    File sourceFilePath = new File(sourcePath);
    if (sourceFilePath.exists()) {
        Collection<java.io.File> sourceFiles = FileUtils.listFiles(sourceFilePath, new String[]{"txt"}, false);

        for (File sourceFile : sourceFiles) {
            File lockFile = new File(sourceFile.getPath() + ".lock");
            if (!lockFile.exists()) {
                executorService.execute(new SampleFileWorker(sourceFile.getPath(), archivePath, random.nextInt(10000)));
            }
        }
        // This will make the executor accept no new threads
        // and finish all existing threads in the queue
        try {
            executorService.shutdown();
            executorService.awaitTermination(10000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException ignored) {
        }
        System.out.printf("%nFinished all threads.%n");
    }
    else {
        System.out.printf("%s doesn't exist. No work to do.%n", sourceFilePath);
    }
}
The SampleFileWorker class looks like this:
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;

public class SampleFileWorker implements Runnable {

    private final String sourcePath;
    private final String archivePath;
    private final int testDelay;

    public SampleFileWorker(String sourcePath, String archivePath, int testDelay) {
        this.sourcePath = sourcePath;
        this.archivePath = archivePath;
        this.testDelay = testDelay;
    }

    @Override
    public void run() {

        try {
            File lockFile = new File(sourcePath + ".lock");
            if (!lockFile.exists()) {
                lockFile.createNewFile();
            } else {
                return;
            }

            File sourceFile = new File(sourcePath);
            String archiveFilePath = archivePath.concat(File.separator + sourceFile.getName());
            File archiveFile = new File(archiveFilePath);

            System.out.printf("Simulating work on file %s.%n", sourcePath);
            System.out.printf("Starting: %s%n", sourcePath);
            System.out.printf("Delay:    %s%n", testDelay);

            try {
                Thread.sleep(testDelay);
            } catch (InterruptedException ignored) {
            }

            System.out.printf("Done with: %s%n", sourcePath);
            System.out.printf("Archiving %s to %s.%n", sourceFile, archivePath);

            FileUtils.moveFile(sourceFile, archiveFile);
            sourceFile.delete();
            lockFile.delete();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

No comments:

Post a Comment