2013-04-25 11 views
6

Mam dużą liczbę zdjęć do pobrania z serwera i chcę pobrać kilka zdjęć o wyższym priorytecie niż inne, dlatego zaimplementowałem mój własny ThreadPoolExecutor, który zwraca FutureTask implementuje Comparable, ale wydaje się nie działać. Zadania są mniej więcej przetwarzane w kolejności, w jakiej je dodaję do kolejki. Mam debugowane BlockingQueue z mojego ThreadPoolExecutor i dowiedziałem się, że po dodaniu mojego Runnable z wyższym priorytetem, nie jest przesunięty do góry na górze kolejki. Oto kodThreadPoolExecutor wspierany przez PriorityBlockingQueue wydaje się nie działać

public class PriorityThreadPoolExecutor extends ThreadPoolExecutor { 

    public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, 
      long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { 
     super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); 
    } 

    protected <T> RunnableFuture<T> newTaskForValue(Runnable runnable, T value) { 
     return new ComparableFutureTask<T>(runnable, value); 
    } 

    protected class ComparableFutureTask<T> 
    extends FutureTask<T> implements Comparable<ComparableFutureTask<T>> { 

     private Object object; 

     public ComparableFutureTask(Runnable runnable, T result) { 
      super(runnable, result); 
      object = runnable; 
     } 

     @Override 
     @SuppressWarnings({ "unchecked", "rawtypes" }) 
     public int compareTo(ComparableFutureTask<T> o) { 
      if (this == o) { 
       return 0; 
      } 
      if (o == null) { 
       return -1; // this has higher priority than null 
      } 
      if (object != null && o.object != null) { 
       if (object.getClass().equals(o.object.getClass())) { 
        if (object instanceof Comparable) { 
         return ((Comparable) object).compareTo(o.object); 
        } 
       } 
      } 
      return 0; 
     } 
    } 

} 

I dodać zadania do puli w ten sposób:

public BitmapLoader(Context context){ 
     mThreadPoolExecutor = new PriorityThreadPoolExecutor(10, Integer.MAX_VALUE,//corepool and maxpool 
       1L, TimeUnit.SECONDS,//keep alive idle threads 
       new PriorityBlockingQueue<Runnable>());//priority queue for jobs 
    } 

public void queuePhoto(String url, ImageView imageView, int priority) {  
    BitmapToLoad p = new BitmapToLoad(url, imageView, priority); 
    final RunnableFuture<Object> futureTask = 
      mThreadPoolExecutor.newTaskForValue(new BitmapLoaderRunnable(p), null); 
    Log.d("BitmapLoader", "Scheduling job with priority " + priority); 
    mThreadPoolExecutor.execute(futureTask); 
} 

Moi BitmapLoaderRunnableComparable narzędzia i kiedy debugowania metoda compareTo jest nazywany. Co ja robię źle? Dzięki

EDIT: poniżej jest kod z moich runnables

private class BitmapLoaderRunnable implements Runnable, Comparable<BitmapLoaderRunnable> { 
     private BitmapToLoad bitmapToLoad; 

     public BitmapLoaderRunnable(BitmapToLoad bitmap) { 
      this.bitmapToLoad = bitmap; 
     } 

     @Override 
     public void run() { 
      try{ 
       if(imageViewReused(bitmapToLoad)) 
        return; 
       Thread.sleep(1000); 
       Bitmap bmp = getBitmap(bitmapToLoad.url); 
       BitmapCache.put(bitmapToLoad.url, bmp); 
       if(imageViewReused(bitmapToLoad)) 
        return; 
       BitmapDisplayer bd = new BitmapDisplayer(bmp, bitmapToLoad); 
       mHandler.post(bd); 
      } catch(Throwable th){ 
       th.printStackTrace(); 
      } 
     } 

     @Override 
     public int compareTo(BitmapLoaderRunnable other) { 
      return this.bitmapToLoad.priority - other.bitmapToLoad.priority; 
     } 
    } 
+0

Proponuję podzielić się odpowiednimi częściami 'BitmapLoaderRunnable' na wypadek, gdyby tam były błędy. –

+0

Czy jesteś pewien, że w kolejce jest wystarczająco dużo zadań oczekujących, ponieważ corePoolSize = 10? – mki

+0

Tak, aby to wypróbować Ustawiłem corePool i maxPool na 1, a następnie umieszczam Thread.sleep (1000) w każdym z Runnables, nadal zachowuję się tak samo ... Zmodyfikowałem pytanie, aby pokazać moje Runnables – chopchop

Odpowiedz

8

Szef PriorityQueue jest elementem najmniej. więc jeśli chcesz najpierw uzyskać priorytet najwyższy, musisz cofnąć porównanie.

@Override 
    public int compareTo(BitmapLoaderRunnable other) { 
     return other.bitmapToLoad.priority - this.bitmapToLoad.priority; 
    } 
+3

O mój boże, spędził cały wczoraj próbując napraw to, grrrrrrrrrrrrrr. To nauczy mnie od teraz właściwie czytać dokumenty. Dzięki wielkie! – chopchop

Powiązane problemy