2011-10-17 15 views
17

Android NDK'de çoğunlukla yerel kod çalıştıran bir sosyal oyun üzerinde çalışıyorum. Oyun 3 ana ndk pthreads vardır:Bir iş parçacığı havuzuna görev gönderme, RejectedExecutionException verir

  1. bir oyun iplik
  2. bir sunucu iletişim iplik
  3. java, bundan daha

Diğer (Renderer.onRender aracılığıyla denir) ana render iplik , "yazı" "Gönder", yan, biz ScheduledExecutorService kendi ile kendi iş parçacığı olarak çoğaltılır AdWhirl'in kullanıyoruz, ancak biz her çağrıyı için "zamanlama" sardırırsın RejectedExecutionException yakalamak için try-catch bloğu ile vs "start". Ancak, sunduğumuz her yeni sürümde korkunç RejectedExecutionException hala var.

Android Market'ten yığın takibi benim için daha fazla ipucu bırakmıyor ve QA departmanımız da test sırasında zorlukla karşılaşılan problemi tespit etmeyi zor buluyor (sadece kullanıcılarımız kilitlenme bildirdi). Bizim kullanıcıların sadece küçük bir kısmını etkiler ama yine de

java.util.concurrent.RejectedExecutionException 
at   java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1876) 
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:774) 
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1295) 
at android.os.AsyncTask.execute(AsyncTask.java:394) 
at c.onProgressUpdate(Unknown Source) 
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:432) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:123) 
at android.app.ActivityThread.main(ActivityThread.java:4632) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:521) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
at dalvik.system.NativeStart.main(Native Method) 

    java.util.concurrent.RejectedExecutionException: pool=128/128, queue=10/10 
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1961) 
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:794) 
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1315) 
at android.os.AsyncTask.execute(AsyncTask.java:394) 
at c.onProgressUpdate(Unknown Source) 
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:432) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:123) 
at android.app.ActivityThread.main(ActivityThread.java:3691) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:507) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605) 
at dalvik.system.NativeStart.main(Native Method) 

    java.util.concurrent.RejectedExecutionException 
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1876) 
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:774) 
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1295) 
at android.os.AsyncTask.execute(AsyncTask.java:394) 
at c.onProgressUpdate(Unknown Source) 
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:432) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:123) 
at android.app.ActivityThread.main(ActivityThread.java:4627) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:521) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
at dalvik.system.NativeStart.main(Native Method) 

cevap

13
Sen kodunu kontrol etmek gerekir

, bu kadar yaratıyor (küçük porsiyon yüklemek yüksek sayıda baz ile karşılaştırıldığında) haftada 7000'den fazla çöküyor olduğu AsyncTask'a izin verilenden çok fazla.

policy

private static final int CORE_POOL_SIZE = 1; 
private static final int MAXIMUM_POOL_SIZE = 10; 
private static final int KEEP_ALIVE = 10; 

Not ayarlanır: tabii mümkün olduğunca verimli gibi şeyleri tutmaya gerekirken bu Android

+0

! İpucunuz için teşekkürler, boyutu artırmak veya herhangi bir sınır var mıdır? Kodumuzda, pek çok AsyncTask kullanmıyoruz, ancak ScheduledExecutorService ve diğer yürütücüler kullanıyoruz ve daha büyük threadpool belirtiyoruz. Bu icracıların büyük bir kısmı var, tüm icracıların toplam sayısı için herhangi bir sınırlama var mı? Kombine uygulama çapında iş parçacığı sayısı sınırı varsa, bunu bir seferde kontrol etmem gerekecek ... uygulamalarımız 20'den fazla iş parçacığıyla çalışıyor ... – Zennichimaro

+0

Diane'e göre bir sınırlama yoktur Ancak, 10'larda kalmak için en iyi yöntemdir. [Azami havuz boyutu] 'nu ayarlayabilirsiniz (http://developer.android.com/reference/java/util/concurrent/ThreadPoolExecutor.html#setMaximumPoolSize (int)) – Reno

+1

Daha az Runnable ve AsyncTask kullanmak için uygulamayı yeniden yazdığımdan ve şimdi çalışıyor ve artık herhangi bir RejectedExecutionException görmedim. Reno ve Diane'e teşekkürler! – Zennichimaro

17

farklı sürümleri değişir, hiçbir keyfi yok Çalıştırmak için "izin verilir" iş parçacığı sayısına sınırlamanız, kodunuzun nasıl yapılandırıldığına bağlıdır.

ThreadPoolExecutor sınıfısınıfı çok iyi belgelenmiş ve gördüğünüz sorunun kaynağıdır.

<javac debug="true" debuglevel="lines,vars,source" /> 

Ya o ya Obfuscation size: Ben,

Sana Ant ile bu bina konum ve Javac düğümünde bu parametreler kullanılarak olmadığını tahmin ediyorum Başlangıç ​​olarak kontrol recommend reading through it ediyorum

c.onProgressUpdate(Unknown Source) 

Bu ThreadPoolExecutor için geçerli ICS 4.0.4 kaynağıdır: görünüşte normal bir yığın izlemesi en önemli bölümü olması gereken yerine basitçe yaydığında nedeni vardır kullanıyor.AbortPolicy olarak bunu temelde görebileceğiniz bir catch-all her zaman bir istisna atar: Ayrıca

/** 
* A handler for rejected tasks that throws a 
* {@code RejectedExecutionException}. 
*/ 

public static class AbortPolicy implements RejectedExecutionHandler { 
    /** 
    * Creates an {@code AbortPolicy}. 
    */ 
    public AbortPolicy() { } 

    /** 
    * Always throws RejectedExecutionException. 
    * 
    * @param r the runnable task requested to be executed 
    * @param e the executor attempting to execute this task 
    * @throws RejectedExecutionException always. 
    */ 
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 
     throw new RejectedExecutionException("Task " + r.toString() + 
              " rejected from " + 
              e.toString()); 
    } 
} 

, sen defaultHandler ThreadPoolExecutor üstündeki ilan bulacaksınız: Sonunda

private static final RejectedExecutionHandler defaultHandler = new AbortPolicy(); 

, Eğer ThreadPoolExecutor için varsayılan Oluşturucu bakarsak:

public ThreadPoolExecutor(int corePoolSize, 
          int maximumPoolSize, 
          long keepAliveTime, 
          TimeUnit unit, 
          BlockingQueue<Runnable> workQueue, 
          ThreadFactory threadFactory) { 
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, 
     threadFactory, defaultHandler); 
} 

sen onun de AbortPolicy sınıfıdır oluyor ki kullanılarak kendisini başlatmasını olduğunu göreceksiniz RejectedExecutionHandler hatası. Bir kullanırken bunun bir örneğini oluşturabilir ya yüzden

/** 
* A handler for rejected tasks that silently discards the 
* rejected task. 
*/ 
public static class DiscardPolicy implements RejectedExecutionHandler { 
    /** 
    * Creates a {@code DiscardPolicy}. 
    */ 
    public DiscardPolicy() { } 

    /** 
    * Does nothing, which has the effect of discarding task r. 
    * 
    * @param r the runnable task requested to be executed 
    * @param e the executor attempting to execute this task 
    */ 
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 
    } 
} 

diğer 3 ThreadPoolExecutor kurucular, bir işleyici seçeneği şunlardır:

ThreadPoolExecutor aynı zamanda gibi varsayılan olarak ayarlayabilirsiniz birkaç diğer RejectedExecutionHandler alt sınıfa dahildir yönteminde sunulan

package com.justinbuser; 

import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.Executors; 
import java.util.concurrent.RejectedExecutionException; 
import java.util.concurrent.RejectedExecutionHandler; 
import java.util.concurrent.ThreadFactory; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 

public class NoThrowThreadPool extends ThreadPoolExecutor { 

    private static final RejectedExecutionHandler defaultHandler = new AdoptPolicy(); 

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { 
     super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); 
     setRejectedExecutionHandler(defaultHandler); 
    } 

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

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, 
      RejectedExecutionHandler handler) { 
     super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); 
    } 

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, 
      ThreadFactory threadFactory, RejectedExecutionHandler handler) { 
     super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler); 
    } 

    public static class AdoptPolicy extends ThreadPoolExecutor.AbortPolicy { 

     @Override 
     public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 
      new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()).printStackTrace(); 
     } 
    } 
} 
+0

Anladım, rehber için teşekkürler! Tutulma üzerinde çalışıyorum ve yapıyorum, javac parametrelerinden herhangi birini değiştirmedim, bu yüzden javac hata ayıklayıcısı varsayılan olarak ayarlanmadıkça, bu yapıma dahil edilmeyecek. Evet, bu çözmek için zor ve zaman alıcı bir sorundur. Ben de herhangi bir çözüm buldum ve o zamandan beri AdWhirl yerine Google'ın AdMob aracılığına geçmiştir. Bu, Reddedilen Etki Sorunu'nu başarıyla önleyebilir: Zamanım olduğunda tekrar bir göz atacağım. Teşekkürler! – Zennichimaro

+0

@Justin Cevabım güncel değil, haklısınız (yukarı-oy vs.). Ayrıca bu bir forum değil, ben gürültü düzenledim [lütfen SSS'leri okuyun] (http://stackoverflow.com/questions/how-to-answer). – Reno

İlgili konular