All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bolts.AndroidExecutors Maven / Gradle / Ivy

Go to download

Bolts is a collection of low-level libraries designed to make developing mobile apps easier.

There is a newer version: 1.4.0
Show newest version
/*
 *  Copyright (c) 2014, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
package bolts;

import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * This was created because the helper methods in {@link java.util.concurrent.Executors} do not work
 * as people would normally expect.
 *
 * Normally, you would think that a cached thread pool would create new threads when necessary,
 * queue them when the pool is full, and kill threads when they've been inactive for a certain
 * period of time. This is not how {@link java.util.concurrent.Executors#newCachedThreadPool()}
 * works.
 *
 * Instead, {@link java.util.concurrent.Executors#newCachedThreadPool()} executes all tasks on
 * a new or cached thread immediately because corePoolSize is 0, SynchronousQueue is a queue with
 * size 0 and maxPoolSize is Integer.MAX_VALUE. This is dangerous because it can create an unchecked
 * amount of threads.
 */
/* package */ final class AndroidExecutors {

  private static final AndroidExecutors INSTANCE = new AndroidExecutors();

  private final Executor uiThread;

  private AndroidExecutors() {
    uiThread = new UIThreadExecutor();
  }

  /**
   * Nexus 5: Quad-Core
   * Moto X: Dual-Core
   *
   * AsyncTask:
   *   CORE_POOL_SIZE = CPU_COUNT + 1
   *   MAX_POOL_SIZE = CPU_COUNT * 2 + 1
   *
   * https://github.com/android/platform_frameworks_base/commit/719c44e03b97e850a46136ba336d729f5fbd1f47
   */
  private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
  /* package */ static final int CORE_POOL_SIZE = CPU_COUNT + 1;
  /* package */ static final int MAX_POOL_SIZE = CPU_COUNT * 2 + 1;
  /* package */ static final long KEEP_ALIVE_TIME = 1L;

  /**
   * Creates a proper Cached Thread Pool. Tasks will reuse cached threads if available
   * or create new threads until the core pool is full. tasks will then be queued. If an
   * task cannot be queued, a new thread will be created unless this would exceed max pool
   * size, then the task will be rejected. Threads will time out after 1 second.
   *
   * Core thread timeout is only available on android-9+.
   *
   * @return the newly created thread pool
   */
  public static ExecutorService newCachedThreadPool() {
    ThreadPoolExecutor executor =  new ThreadPoolExecutor(
        CORE_POOL_SIZE,
        MAX_POOL_SIZE,
        KEEP_ALIVE_TIME, TimeUnit.SECONDS,
        new LinkedBlockingQueue());

    allowCoreThreadTimeout(executor, true);

    return executor;
  }

  /**
   * Creates a proper Cached Thread Pool. Tasks will reuse cached threads if available
   * or create new threads until the core pool is full. tasks will then be queued. If an
   * task cannot be queued, a new thread will be created unless this would exceed max pool
   * size, then the task will be rejected. Threads will time out after 1 second.
   *
   * Core thread timeout is only available on android-9+.
   *
   * @param threadFactory the factory to use when creating new threads
   * @return the newly created thread pool
   */
  public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
    ThreadPoolExecutor executor =  new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            KEEP_ALIVE_TIME, TimeUnit.SECONDS,
            new LinkedBlockingQueue(),
            threadFactory);

    allowCoreThreadTimeout(executor, true);

    return executor;
  }

  /**
   * Compatibility helper function for
   * {@link java.util.concurrent.ThreadPoolExecutor#allowCoreThreadTimeOut(boolean)}
   *
   * Only available on android-9+.
   *
   * @param executor the {@link java.util.concurrent.ThreadPoolExecutor}
   * @param value true if should time out, else false
   */
  @SuppressLint("NewApi")
  public static void allowCoreThreadTimeout(ThreadPoolExecutor executor, boolean value) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
      executor.allowCoreThreadTimeOut(value);
    }
  }

  /**
   * An {@link java.util.concurrent.Executor} that executes tasks on the UI thread.
   */
  public static Executor uiThread() {
    return INSTANCE.uiThread;
  }

  /**
   * An {@link java.util.concurrent.Executor} that runs tasks on the UI thread.
   */
  private static class UIThreadExecutor implements Executor {
    @Override
    public void execute(Runnable command) {
      new Handler(Looper.getMainLooper()).post(command);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy