diff options
Diffstat (limited to 'adservices/service-core/java/com/android/adservices/concurrency/AdServicesExecutors.java')
-rw-r--r-- | adservices/service-core/java/com/android/adservices/concurrency/AdServicesExecutors.java | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/adservices/service-core/java/com/android/adservices/concurrency/AdServicesExecutors.java b/adservices/service-core/java/com/android/adservices/concurrency/AdServicesExecutors.java index 379d181ed2..0795441e62 100644 --- a/adservices/service-core/java/com/android/adservices/concurrency/AdServicesExecutors.java +++ b/adservices/service-core/java/com/android/adservices/concurrency/AdServicesExecutors.java @@ -17,14 +17,18 @@ package com.android.adservices.concurrency; import android.annotation.NonNull; +import android.annotation.SuppressLint; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; /** * ALl executors of the PP API module. @@ -34,14 +38,35 @@ import java.util.concurrent.TimeUnit; // TODO(b/224987182): set appropriate parameters (priority, size, etc..) for the shared thread pools // after doing detailed analysis. Ideally the parameters should be backed by PH flags. public final class AdServicesExecutors { - // We set the minimal number of threads for background executor to 4 and lightweight executor to - // 2 since Runtime.getRuntime().availableProcessors() may return 1 or 2 for low-end devices. - // This may cause deadlock for starvation in those low-end devices. + // We set the minimal number of threads for background executor to 4 and lightweight & scheduled + // executors to 2 since Runtime.getRuntime().availableProcessors() may return 1 or 2 for + // low-end devices. This may cause deadlock for starvation in those low-end devices. private static final int MIN_BACKGROUND_EXECUTOR_THREADS = 4; private static final int MIN_LIGHTWEIGHT_EXECUTOR_THREADS = 2; + private static final int MAX_SCHEDULED_EXECUTOR_THREADS = 4; + + private static final String LIGHTWEIGHT_NAME = "lightweight"; + private static final String BACKGROUND_NAME = "background"; + private static final String SCHEDULED_NAME = "scheduled"; + private static final String BLOCKING_NAME = "blocking"; + + private static ThreadFactory getFactory(final String threadPrefix) { + return new ThreadFactory() { + private final AtomicLong mThreadCount = new AtomicLong(0L); + + @SuppressLint("DefaultLocale") + @Override + public Thread newThread(Runnable runnable) { + Thread thread = Executors.defaultThreadFactory().newThread(runnable); + thread.setName( + String.format("%s-%d", threadPrefix, mThreadCount.incrementAndGet())); + return thread; + } + }; + } private static final ListeningExecutorService sLightWeightExecutor = - // Always use at least two threads, so that clients can't depend on light weight + // Always use at least two threads, so that clients can't depend on light-weight // executor tasks executing sequentially MoreExecutors.listeningDecorator( new ThreadPoolExecutor( @@ -54,7 +79,8 @@ public final class AdServicesExecutors { Runtime.getRuntime().availableProcessors() - 2), /* keepAliveTime = */ 60L, TimeUnit.SECONDS, - new LinkedBlockingQueue<>())); + new LinkedBlockingQueue<>(), + getFactory(LIGHTWEIGHT_NAME))); /** * Functions that don't do direct I/O and that are fast (under ten milliseconds or thereabouts) @@ -78,7 +104,8 @@ public final class AdServicesExecutors { Runtime.getRuntime().availableProcessors()), /* keepAliveTime = */ 60L, TimeUnit.SECONDS, - new LinkedBlockingQueue<>())); + new LinkedBlockingQueue<>(), + getFactory(BACKGROUND_NAME))); /** * Functions that directly execute disk I/O, or that are CPU bound and long-running (over ten @@ -93,8 +120,29 @@ public final class AdServicesExecutors { return sBackgroundExecutor; } + private static final ScheduledThreadPoolExecutor sScheduler = + new ScheduledThreadPoolExecutor( + /* corePoolSize = */ Math.min( + MAX_SCHEDULED_EXECUTOR_THREADS, + Runtime.getRuntime().availableProcessors()), + getFactory(SCHEDULED_NAME)); + + /** + * Functions that require to be run with a delay, or have timed executions should run on this + * Executor + * + * <p>Example includes having timeouts on Futures + * + * @return + */ + @NonNull + public static ScheduledThreadPoolExecutor getScheduler() { + return sScheduler; + } + private static final ListeningExecutorService sBlockingExecutor = - MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); + MoreExecutors.listeningDecorator( + Executors.newCachedThreadPool(getFactory(BLOCKING_NAME))); /** * Functions that directly execute network I/O, or that block their thread awaiting the progress |