gav
gav

Reputation: 29122

Simple Thread Management - Java - Android

I have an application which spawns a new thread when a user asks for an image to be filtered.

This is the only type of task that I have and all are of equal importance.

If I ask for too many concurrent threads (Max I ever want is 9) the thread manager throws a RejectedExecutionException.

At the minute what I do is;

// Manage Concurrent Tasks
private Queue<AsyncTask<Bitmap,Integer,Integer>> tasks = new LinkedList<AsyncTask<Bitmap,Integer,Integer>>();

@Override
public int remainingSize() {
    return tasks.size();
}

@Override
public void addTask(AsyncTask<Bitmap, Integer, Integer> task) {
    try{
        task.execute(currentThumbnail);
        while(!tasks.isEmpty()){
            task = tasks.remove();
            task.execute(currentThumbnail);
        }
    } catch (RejectedExecutionException r){
        Log.i(TAG,"Caught RejectedExecutionException Exception - Adding task to Queue");
        tasks.add(task);
    }
}

Simply add the rejected task to a queue and the next time a thread is started the queue is checked to see if there is a backlog.

The obvious issue with this is that if the final task gets rejected on its first attempt it will never be restarted (Until after it's no longer needed).

Just wondering if there's a simple model I should use for managing this sort of thing. I need tasks to notify the queue when they are done.

Upvotes: 8

Views: 14318

Answers (3)

tip
tip

Reputation: 1

Maybe an option is to have the task wait on a blocking queue (of bitmaps) instead of taking bitmap as a parameter, but you will have to add a way for the task(s) to terminate.

Upvotes: 0

CommonsWare
CommonsWare

Reputation: 1006704

The reason for the RejectedExecutionException is because AsyncTask implements a thread pool of its own (per Mr. Martelli's answer), but one that is capped at a maximum of 10 simultaneous tasks. Why they have that limit, I have no idea.

Hence, one possibility is for you to clone AsyncTask, raise the limit (or go unbounded, which is also possible with LinkedBlockingQueue), and use your clone. Then, perhaps, submit the change as a patch to AsyncTask for future Android releases.

Click here to run a Google Code Search for AsyncTask -- the first hit should be the implementation.

If you just want to raise the limit, adjust MAXIMUM_POOL_SIZE to be as big as you're likely to need. If you want to go unbounded, use the zero-argument LinkedBlockingQueue constructor instead of the one being presently used. AFAICT, the rest of the code probably stays the same.

Upvotes: 12

Alex Martelli
Alex Martelli

Reputation: 881635

You seem to have implemented a version of the Thread Pool design pattern -- the wikipedia article points to many helpful articles on the subject, which may help you refine your implementation. I also recommend this Java-specific article which has clear code and explanation.

Upvotes: 3

Related Questions