开发者

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;
     开发者_如何学Python   this.Id = id;
        ConnectionManager.getInstance().push(this);
    }

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

        ConnectionManager.getInstance().didComplete(this);
    }


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.


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.


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.


Why don't you use a Queue instead of ArrayLists? It would fit in here better.


ArrayList is not thread safe, but you're using it with threading. As such, you have different threads getting in each others way. Here's what's probably happening:

  • You call push several times with various runnables. The add method gets called somewhat simultaneously for all of these, but because add is not thread safe, the first one doesn't finish adding before the second one starts adding, so you only end up with one runnable in your queue.

  • Then StartNext is called a bunch of times simultaneously. One of the threads runs "next = queue.Get(), however, another thread also calls "next = queue.Get()" before the first thread has a chance to remove that item from the queue, so both threads end up processing the same runnable.

You will need to either find a threadsafe object to use, or add some type of mutex/locking mechanism to ensure that the various threads don't get in each other's way.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜