Loading core/java/android/os/AsyncTask.java +40 −12 Original line number Diff line number Diff line Loading @@ -21,13 +21,14 @@ import android.annotation.Nullable; import android.annotation.WorkerThread; import java.util.ArrayDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.FutureTask; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; Loading Loading @@ -190,13 +191,19 @@ import java.util.concurrent.atomic.AtomicInteger; public abstract class AsyncTask<Params, Progress, Result> { private static final String LOG_TAG = "AsyncTask"; private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // We want at least 2 threads and at most 4 threads in the core pool, // preferring to have 1 less than the CPU count to avoid saturating // the CPU with background work private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4)); private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final int KEEP_ALIVE_SECONDS = 30; // We keep only a single pool thread around all the time. // We let the pool grow to a fairly large number of threads if necessary, // but let them time out quickly. In the unlikely case that we run out of threads, // we fall back to a simple unbounded-queue executor. // This combination ensures that: // 1. We normally keep few threads (1) around. // 2. We queue only after launching a significantly larger, but still bounded, set of threads. // 3. We keep the total number of threads bounded, but still allow an unbounded set // of tasks to be queued. private static final int CORE_POOL_SIZE = 1; private static final int MAXIMUM_POOL_SIZE = 20; private static final int BACKUP_POOL_SIZE = 5; private static final int KEEP_ALIVE_SECONDS = 3; private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); Loading @@ -206,8 +213,29 @@ public abstract class AsyncTask<Params, Progress, Result> { } }; private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); // Used only for rejected executions. // Initialization protected by sRunOnSerialPolicy lock. private static ThreadPoolExecutor sBackupExecutor; private static LinkedBlockingQueue<Runnable> sBackupExecutorQueue; private static final RejectedExecutionHandler sRunOnSerialPolicy = new RejectedExecutionHandler() { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { android.util.Log.w(LOG_TAG, "Exceeded ThreadPoolExecutor pool size"); // As a last ditch fallback, run it on an executor with an unbounded queue. // Create this executor lazily, hopefully almost never. synchronized (this) { if (sBackupExecutor == null) { sBackupExecutorQueue = new LinkedBlockingQueue<Runnable>(); sBackupExecutor = new ThreadPoolExecutor( BACKUP_POOL_SIZE, BACKUP_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sBackupExecutorQueue, sThreadFactory); sBackupExecutor.allowCoreThreadTimeOut(true); } } sBackupExecutor.execute(r); } }; /** * An {@link Executor} that can be used to execute tasks in parallel. Loading @@ -217,8 +245,8 @@ public abstract class AsyncTask<Params, Progress, Result> { static { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); threadPoolExecutor.allowCoreThreadTimeOut(true); new SynchronousQueue<Runnable>(), sThreadFactory); threadPoolExecutor.setRejectedExecutionHandler(sRunOnSerialPolicy); THREAD_POOL_EXECUTOR = threadPoolExecutor; } Loading Loading
core/java/android/os/AsyncTask.java +40 −12 Original line number Diff line number Diff line Loading @@ -21,13 +21,14 @@ import android.annotation.Nullable; import android.annotation.WorkerThread; import java.util.ArrayDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.FutureTask; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; Loading Loading @@ -190,13 +191,19 @@ import java.util.concurrent.atomic.AtomicInteger; public abstract class AsyncTask<Params, Progress, Result> { private static final String LOG_TAG = "AsyncTask"; private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // We want at least 2 threads and at most 4 threads in the core pool, // preferring to have 1 less than the CPU count to avoid saturating // the CPU with background work private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4)); private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final int KEEP_ALIVE_SECONDS = 30; // We keep only a single pool thread around all the time. // We let the pool grow to a fairly large number of threads if necessary, // but let them time out quickly. In the unlikely case that we run out of threads, // we fall back to a simple unbounded-queue executor. // This combination ensures that: // 1. We normally keep few threads (1) around. // 2. We queue only after launching a significantly larger, but still bounded, set of threads. // 3. We keep the total number of threads bounded, but still allow an unbounded set // of tasks to be queued. private static final int CORE_POOL_SIZE = 1; private static final int MAXIMUM_POOL_SIZE = 20; private static final int BACKUP_POOL_SIZE = 5; private static final int KEEP_ALIVE_SECONDS = 3; private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); Loading @@ -206,8 +213,29 @@ public abstract class AsyncTask<Params, Progress, Result> { } }; private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); // Used only for rejected executions. // Initialization protected by sRunOnSerialPolicy lock. private static ThreadPoolExecutor sBackupExecutor; private static LinkedBlockingQueue<Runnable> sBackupExecutorQueue; private static final RejectedExecutionHandler sRunOnSerialPolicy = new RejectedExecutionHandler() { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { android.util.Log.w(LOG_TAG, "Exceeded ThreadPoolExecutor pool size"); // As a last ditch fallback, run it on an executor with an unbounded queue. // Create this executor lazily, hopefully almost never. synchronized (this) { if (sBackupExecutor == null) { sBackupExecutorQueue = new LinkedBlockingQueue<Runnable>(); sBackupExecutor = new ThreadPoolExecutor( BACKUP_POOL_SIZE, BACKUP_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sBackupExecutorQueue, sThreadFactory); sBackupExecutor.allowCoreThreadTimeOut(true); } } sBackupExecutor.execute(r); } }; /** * An {@link Executor} that can be used to execute tasks in parallel. Loading @@ -217,8 +245,8 @@ public abstract class AsyncTask<Params, Progress, Result> { static { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); threadPoolExecutor.allowCoreThreadTimeOut(true); new SynchronousQueue<Runnable>(), sThreadFactory); threadPoolExecutor.setRejectedExecutionHandler(sRunOnSerialPolicy); THREAD_POOL_EXECUTOR = threadPoolExecutor; } Loading