mercredi 17 août 2016

How to Manage Queue of Runnable Tasks in Android

I have multiple tasks/Runnable (i.e. downloading images from internet), which are generated as the user scrolls through a list in a Android App. I cannot control how many tasks/Runnable are generated at a time, this could in 100. But I want to execute only n(10) tasks in parallel. So, I am planning to build a design, where as soon as a new task/runnable is generated, it will be added to a queue (List) and through Executors.newFixedThreadPool(10), I will execute only first 10 runnable tasks in parallel. Now as soon as the tasks/Runnable are completed, I should be able to remove them from queue (List) and should be able to execute new tasks/Runnable which are in queue, in FIFO. I have two classes for this design. First is "ExecutorManager" which is a singleton class and manages the executions of 10 parallels tasks and second is the "ImageDownloader" class which implements runnable and is responsible to download the image. I am not sure what is the best way to inform the "ExecutorManager" that the task/download is completed and it can execute new task from the queue. I am following FIFO, so I will always start execution from first 10 tasks in the queue, but how will I get to know, which task is completed and which one to remove from the Queue? Thanks in Advance for the help.

public class ImageDownloader implements Runnable{

    DownloadListener mDownloadListener;

    public ImageDownloader(DownloadListener mDownloadListener, String URL){
        this.mDownloadListener = mDownloadListener;
    }


    @Override
    public void run() {
        //Download the Image from Internet
            //ToDo
        //if Success in download
            mDownloadListener.onDownloadComplete();
        //if Error in download
            mDownloadListener.onDownloadFailure();
        //Inform the Executor Manager that the task is complete and it can start new task
         incrementCount();
    }

    private static synchronized void incrementCount(){
        ExecutorManager.getInstance().OnTaskCompleted();// is there a better way to do it
    }
}



public class ExecutorManager {

    private static ExecutorManager Instance;
    ExecutorService executor = Executors.newFixedThreadPool(Constants.NumberOfParallelThread);
    ArrayList<Runnable> ExecutorQueue = new ArrayList<Runnable>();
    int ActiveNumberOfThread = 0;

    private ExecutorManager(){
    }

    public static ExecutorManager getInstance(){

        if(Instance==null){
            Instance = new ExecutorManager();

        }
        return Instance;
    }

    private void executeTask(){
        if(ExecutorQueue.size()>0 && ActiveNumberOfThread < Constants.NumberOfParallelThread){
            ++ActiveNumberOfThread;
            executor.execute(ExecutorQueue.get(0));//Execute the First Task in Queue
        }
    }

    public void enQueueTask(Runnable Task){

        ExecutorQueue.add(Task);
        executeTask();
    }

    public void removeFromQueue(){
        //How to know, which task to remove?
        ExecutorQueue.remove(0);
    }

    public void OnTaskCompleted(){
        --ActiveNumberOfThread;
        removeFromQueue();
        executeTask();
    }

}

Aucun commentaire:

Enregistrer un commentaire