2009-06-13 9 views
7

Ich habe eine Anwendung, die einen neuen Thread hervorbringt, wenn ein Benutzer nach einem Bild fragt, das gefiltert werden soll.Simple Thread Management - Java - Android

Dies ist die einzige Art von Aufgabe, die ich habe und alle gleich wichtig sind.

Wenn ich zu viele gleichzeitige Threads (Max ich jemals will, ist 9) fragt der Thread-Manager eine RejectedExecutionException.

In der Minute was ich tue ist;

// 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); 
    } 
} 

Fügen Sie einfach die abgelehnte Aufgabe in eine Warteschlange und das nächste Mal, wenn ein Thread die Warteschlange gestartet wird geprüft, ob ein Rückstand gibt.

Das offensichtliche Problem dabei ist, dass, wenn die letzte Aufgabe beim ersten Versuch abgelehnt wird, sie nie neu gestartet wird (bis sie nicht mehr benötigt wird).

Ich frage mich nur, ob es ein einfaches Modell gibt, das ich für die Verwaltung dieser Art von Sache verwenden sollte. Ich brauche Aufgaben, um die Warteschlange zu benachrichtigen, wenn sie fertig sind, also weiß ich, dass es Platz gibt, aber ich bin mir nicht sicher, wie.

Mit freundlichen Grüßen

Gavin

Antwort

12

Der Grund für die RejectedExecutionException ist, weil AsyncTask implementiert einen Thread-Pool von seiner eigenen (nach Herrn Martelli Antwort), aber eine, die auf maximal 10 gleichzeitige Aufgaben begrenzt ist. Warum sie diese Grenze haben, habe ich keine Ahnung.

Daher ist eine Möglichkeit für Sie zu klonen AsyncTask, erhöhen Sie die Grenze (oder gehen Sie unbegrenzt, was auch möglich ist mit LinkedBlockingQueue), und verwenden Sie Ihren Klon. Dann, vielleicht, senden Sie die Änderung als Patch an AsyncTask für zukünftige Android-Versionen.

Klicken Sie auf here, um eine Google-Codesuche für AsyncTask auszuführen - der erste Treffer sollte die Implementierung sein.

Wenn Sie nur das Limit erhöhen möchten, passen Sie so groß an, wie Sie wahrscheinlich benötigen. Wenn Sie unbegrenzt arbeiten möchten, verwenden Sie das Null-Argument LinkedBlockingQueue Konstruktor anstelle des derzeit verwendeten. AFAICT, der Rest des Codes bleibt wahrscheinlich derselbe.

+15

Das Limit ist nicht mehr 10. Das Limit wurde eingeführt, weil AsyncTasks nicht dazu gedacht sind, von Dutzenden gefeuert zu werden. Da das Ziel einer solchen Aufgabe darin besteht, die Benutzeroberfläche zu aktualisieren, wäre es ziemlich schlimm, Dutzende von Threads zu haben, die Aktualisierungen verursachen. –

+0

Das Limit beträgt derzeit 5 parallele Threads gemäß http://google.com/codesearch#uX1GffpyOZk/core/java/android/os/AsyncTask.java –

+0

@Grantland Chew: Nein, es ist 5, um mit zu beginnen. Es kann darüber hinaus wachsen. – CommonsWare

3

Sie scheinen eine Version des Thread Pool Entwurfsmuster umgesetzt zu haben - Wikipedia-Artikel verweist auf viele hilfreiche Artikel zu diesem Thema, mit dem Sie Ihre Implementierung verfeinern kann helfen. Ich empfehle auch this Java-specific article, die klaren Code und Erklärung hat.

0

Vielleicht ist eine Option, den Task auf eine blockierende Warteschlange (von Bitmaps) warten zu lassen, anstatt Bitmap als Parameter zu verwenden, aber Sie müssen einen Weg hinzufügen, damit die Task (s) beendet werden.