System to handle the short lived async task I'm developing an application in which there are many short-lived tasks which are run in separate threads. I've developed a generic and reusable system to handle such a requirement. The code snippet given below is using this system code plus the example client code to show how to use the system's API.

package com.demo;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

import java.util.concurrent.TimeUnit;


////////////////////////API to handle short lived async task///////////////////////////////////////////

/*
 * This class holds the threadpool executor instance and provide the submit method which in turn submit the task
 * to executor
 */

class AsyncTaskManager
{
    private ExecutorService service;

public AsyncTaskManager(ExecutorService service){
    this.service = service;
}


public &lt;T&gt; Future&lt;T&gt;  submit(Callable&lt;T&gt; callable){
    Future&lt;T&gt; result = service.submit(callable);
    return result;
}

public void shutdown(){
    service.shutdown();
    try {
        service.awaitTermination(60, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        service.shutdownNow();
    }
    service.shutdownNow();
}

}

/**
 * This is a wrapper class on Task object to make it async
 * @author jayesh
 *
 * @param &lt;T&gt;
 * @param &lt;V&gt;
 */

class AsyncTask&lt;T extends Task&lt;V&gt;, V&gt; implements Callable&lt;V&gt;{
private Task&lt;V&gt; task;

public AsyncTask(Task&lt;V&gt; task){
    this.task = task;
}

@Override
public V call() throws Exception {
    return task.doTask();
}

}

/**
 * Client will implement this interface to perform the task
 * @author jayesh
 *
 * @param &lt;V&gt;
 */

interface Task&lt;V&gt;{
    public  V doTask();
}


/////////////////////////////////////////End of API ////////////////////////////////////////


//////////////////////Use of API by client code /////////////////////////////////////////////

public class AsyncTaskManagerDemo {

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

    AsyncTaskManager taskManager = new AsyncTaskManager(Executors.newCachedThreadPool());

    Task&lt;String&gt; urlLoader = new UrlLoaderTask("http://www.google.com");
    Task&lt;Integer&gt; wordCounter = new WordCounterTask("/var/tmp/test.txt");

    AsyncTask&lt;Task&lt;String&gt;, String&gt; asyncUrlLoader = new AsyncTask&lt;Task&lt;String&gt;, String&gt;(urlLoader);
    AsyncTask&lt;Task&lt;Integer&gt;, Integer&gt; asyncWordCounter = new AsyncTask&lt;Task&lt;Integer&gt;, Integer&gt;(wordCounter);


    Future&lt;String&gt; urlLoaderResult = taskManager.submit(asyncUrlLoader);
    System.out.println(urlLoaderResult.get());

    Future&lt;Integer&gt; wordCounterResult = taskManager.submit(asyncWordCounter);
    System.out.println(wordCounterResult.get());

    taskManager.shutdown();
}
}

/**
 * Task implementation which do the  task and returns result
 * @author xxx
 *
 */

class UrlLoaderTask implements Task&lt;String&gt;
{
private String url;
public UrlLoaderTask(String url){
    this.url = url;
}
@Override
public String doTask(){
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return "returning content of url - " + url;
}
};

/**
 * Task implementation which do the  task and returns result
 * @author xxx
 *
 */

class WordCounterTask implements Task&lt;Integer&gt;
{
private String filePath;
public WordCounterTask(String filePath){
    this.filePath = filePath;
}
@Override
public Integer doTask(){
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return 1000; //returning no of words in a file
}
};


I am looking for a review on my system and its API.
I would strongly recommend a use of Java 8 features to make your library (which has an API) an easier to use system.

Your Task interface should be a @FunctionalInterface. It is one already, but you should make it formal with the annotation:

@FunctionalInterface
interface Task&lt;V&gt;{
    public  V doTask();
}


Now, any time you want a task, you can do things like:

Task&lt;Long&gt; wordcount = () -&gt; countWords("Hello World");


The above is equivalent to:

Task&lt;Long&gt; wordcount = new Task&lt;Long&gt;() {
    @Override
    public Long doTask() {
        return countWords("Hello World");
    }
}


This leads on to the next concern I have with the TaskManager. Here's your code copied:


class AsyncTaskManager
{
    private ExecutorService service;

    public AsyncTaskManager(ExecutorService service){
        this.service = service;
    }


    public &lt;T&gt; Future&lt;T&gt;  submit(Callable&lt;T&gt; callable){
        Future&lt;T&gt; result = service.submit(callable);
        return result;
    }

    public void shutdown(){
        service.shutdown();
        try {
            service.awaitTermination(60, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            service.shutdownNow();
        }
        service.shutdownNow();
    }

}



The following concern me:


The service should be final, make it immutable.
The service is created outside the class, but then shut down inside the class. This is asymmetrical. If the service is created outside then it should be shut-down outside.
The class should be AutoClosable instead of having the shutdown() method.


Again, I would use a Java-8 concept called a supplier. Instead of passing in a service, pass in a method that can create a service. That way, you can still add a custom service, but you create it, not the people who call you.

About the try/catch block in the shutdown... you should use a finally block instead of what you currently have, and also, you should reset the interrupted flag if there is an interrupt. This is better than doing nothing (which is what you currently do). It avoids the exception, but makes the next thing that checks have to handle it. In other words, you pass the buck.

This is how it would look:

class AsyncTaskManager implements AutoClosable {
    private final ExecutorService service;

    public AsyncTaskManager(Supplier&lt;ExecutorService&gt; service){
        this.service = service.get();
    }

    public &lt;T&gt; Future&lt;T&gt;  submit(Callable&lt;T&gt; callable){
        return service.submit(callable);
    }

    @Override        
    public void close() {

        service.shutdown();

        try {
            service.awaitTermination(60, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            service.shutdownNow();
        }
    }

}