Android 线程

Android 中线程的状态

Android 中线程的状态主要有以下四种:

  • Thread
  • AsyncTask
  • HandlerThread
  • IntentService

Thread

Thread 不必说,就是普通的线程,线程的作用主要是执行耗时任务。

AsyncTask

封装了 Handler 和线程池的抽象类。

4 个核心方法:

  1. onPreExecute()
    主线程中执行,做一些准备工作。

  2. doInBackgound(Params…params)
    线程池中执行,执行异步任务。返回结果到 onPostExecute。通过 publishProgress 来更新任务进度,publishProgress 会调用 onProgressUpdate 方法。

  3. onProgressUpdate(Progress…values)
    主线程中执行,后台任务执行进度发生变化时被调用。

  4. onPostExecute(Result result)
    主线程中执行,异步任务执行完后调用,result 参数是 doInBackground 的返回值。

使用注意事项:

  • AsyncTask 的类必须在主线程加载。
  • AsyncTask 的对象必须在主线程中创建。
  • execute 方法必须在 UI 线程调用。
  • 不要在程序中直接调用以上四个方法。
  • 一个 AsyncTask 对象只能 execute 一次。
  • Android 3.0 之后,AsyncTask 默认采用一个线程来串行执行任务,可使用 executeOnExecutor 方法来并行执行。

工作原理:

AsyncTask 内有两个线程池(SerialExecutor 和 THREAD_POOL_EXECUTOR),一个 Handler(InternalHandler),其中 SerialExecutor 用于线程池的排队,而 THREAD_POOL_EXECUTOR 用于真正地执行任务。

HandlerThread

封装了 Handler 的 Thread。

IntentService

封装了 HandlerThread 的 Service 抽象类。


Android 中的线程池

线程池的优点:

  • 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
  • 能有效控制线程池的最大并发数,避免大量的线程之间因为互相抢占系统资源而导致的阻塞现象。
  • 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。

ThreadPoolExecutor

ThreadPoolExecutor 是线程池的实现,其中一个构造函数如下:

public ThreadPoolExecutor(int corePoolSize, 
                          int maximumPoolSize, 
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory)
  • corePoolSize
    线程池的核心线程数,默认核心线程会一直存活,即使处于闲置状态。

  • maximumPoolSize
    线程池所能容纳的最大线程数,超过这个数后,新任务将被阻塞。

  • keepAliveTime
    非核心线程闲置时的超时时长,超过这个时长,非核心线程将被回收。当 ThreadPoolExecutor 的 allowCoreThreadTimeOut 属性设置为 ture 后,keepAliveTime 同样作用于核心线程。

  • unit
    keepAliveTime的时间单位,常用的有TimeUnit.MILLISECONDS,TimeUnit.SECONDS,TimeUnit.MINUTES 等。

  • workQueue
    线程池中的任务队列,通过 execute 方法提交的 Runnable 对象会存储在和这个参数中。

  • threadFactory
    线程工厂,提供新线程。

ThreadPoolExecutor 执行任务的规则:

  1. 如果线程池中线程数量没有达到核心线程数,直接启动一个新线程来执行任务。

  2. 如果线程池中的线程数量达到或超过核心线程数,任务会被插到任务队列中排队等待执行。

  3. 如果 2 中无法将任务插入队列,这往往是由于队列已满,这个时候如果线程数量没有达到最大值,启动一个新线程来执行。

  4. 如果 3 中线程数已经达到最大值,拒绝执行此任务,ThreadPoolExecutor 调用 RejectedExecutionHandlerrejectedExecution 方法来通知调用者。

AsyncTask 中线程池的配置情况:

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE = 1;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

它的规格如下:

  • 核心线程数 CPU 核心数 + 1
  • 最大线程数 CPU 核心数*2 + 1
  • 核心线程无超时,非核心线程闲置超时时间 1 秒
  • 任务队列容量 128

线程池的分类

  • FixedThreadPool

    线程数量固定,没有非核心线程。更快地相应外界的请求。

    ExecutorService service = Executors.newFixedThreadPool(2);
    
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
  • CachedThreadPool

    线程数量不定,没有核心线程,非核心数量没有限制。主要用于执行大量的耗时较少的任务。

    ExecutorService service = Executors.newCachedThreadPool();
    
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • ScheduledThreadPool

    线程数量不定,核心线程数量固定,非核心数量没有限制。主要用于执行定时任务和具有固定周期的重复任务。

    ExecutorService service = Executors.newScheduledThreadPool(2);
    
    
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }
    
  • SingleThreadExecutor

    只有一个线程,不需要处理线程同步。

    ExecutorService service = Executors.newSingleThreadExecutor();
    
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    

猜你喜欢

转载自blog.csdn.net/gdeer/article/details/53023459