Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a queue of runnables

I am trying to implement a queue of runnables to be executed one after another(meaning the next in the queue will execute after the other has completed) during an asynchronous task. I wrote a Manager to manage these runnables and task that is a runnable itself. I then get the first task in the Asynchronous task and run it in hopes that it will run through the queue, however It just ends up running the first runnable twice. Can anyone help me with the code I have been working with or point me to an example that may be of some help?

public class ConnectionManager {

    public static final int MAX_CONNECTIONS = 15;

    private ArrayList<Runnable> active = new ArrayList<Runnable>();
    private ArrayList<Runnable> queue = new ArrayList<Runnable>();

    private static ConnectionManager instance;

    public static ConnectionManager getInstance() {
        if (instance == null)
            instance = new ConnectionManager();
        return instance;
    }

    public void push(Runnable runnable) {
        queue.add(runnable);
        if (active.size() < MAX_CONNECTIONS)
            startNext();
    }

    private void startNext() {
        if (!queue.isEmpty()) {
            Runnable next = queue.get(0);
            queue.remove(0);
            active.add(next);

            Thread thread = new Thread(next);
            thread.start();
        }
    }

    public void didComplete(Runnable runnable) {
        active.remove(runnable);
        startNext();
    }
}

public class Task implements Runnable {
    Context con;
    String xmlFile;
    File taskFile;
    String Id;

    public void create(Context context, String xml, File task, String id) {
        this.con = context;
        this.xmlFile = xml;
        this.taskFile = task;
        this.Id = id;
        ConnectionManager.getInstance().push(this);
    }

    @Override
    public void run() {
        User.SendTask(con, xmlFile, taskFile, Id);

        ConnectionManager.getInstance().didComplete(this);
    }
like image 209
ninjasense Avatar asked Sep 14 '11 15:09

ninjasense


3 Answers

how about using Executors.newSingleThreadExecutor()? http://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor%28java.util.concurrent.ThreadFactory%29

API description explains that this executor execute only one task sequentially and has unlimited queue. I think this one can satisfies your requirement.

like image 89
kingori Avatar answered Oct 09 '22 19:10

kingori


I'm doing something very similar in one of my apps, and what I do to keep it clean is to make my queue contain the data and not the threads to execute. I use a single AsyncTask for my execution (which pulls from a thread pool that the system allocates...might make mgmt easier for you), and in the doInBackground method of it, I pull data out of the queue, operate on it, and call my entry method again in onPostExecute.

like image 28
Rich Avatar answered Oct 09 '22 21:10

Rich


There's no need to build this yourself, just use a ThreadPoolExecutor to do it for you. construct one with a minPool size of 1, and a max pool size of 15, and you should be all set.

like image 27
superfell Avatar answered Oct 09 '22 19:10

superfell