zoukankan      html  css  js  c++  java
  • Android中线程和线程池

    我们知道线程是CPU调度的最小单位。在Android中主线程是不能够做耗时操作的,子线程是不能够更新UI的。在Android中,除了Thread外,扮演线程的角色有很多,如AsyncTask,IntentService和HandlerThread等等。由于内容过多,所以将分为上下两部分,第一部分主要和大家谈谈Android中的线程,以及在Android中的常用的线程池。第二部分我们一起来了解一下AsyncTask的使用和工作原理。

    1、HandlerThread

    HandlerThread是Thread的子类,它是一种可以使用Handler的Thread,它的实现比较简单。我们来看看它的源码:

     1 package android.os;
     2 
     3 public class HandlerThread extends Thread {
     4     int mPriority;
     5     int mTid = -1;
     6     Looper mLooper;
     7 
     8     public HandlerThread(String name) {
     9         super(name);
    10         mPriority = Process.THREAD_PRIORITY_DEFAULT;
    11     }
    12     
    13 
    14       public HandlerThread(String name, int priority) {
    15         super(name);
    16         mPriority = priority;
    17     }
    18     
    19 
    20        protected void onLooperPrepared() {
    21     }
    22 
    23 
    24 
    25     @Override
    26     public void run() {
    27         mTid = Process.myTid();
    28         Looper.prepare();
    29         synchronized (this) {
    30             mLooper = Looper.myLooper();
    31             notifyAll();
    32         }
    33         Process.setThreadPriority(mPriority);
    34         onLooperPrepared();
    35         Looper.loop();
    36         mTid = -1;
    37     }
    38     
    39 
    40 
    41      public Looper getLooper() {
    42         if (!isAlive()) {
    43             return null;
    44         }
    45         
    46         // If the thread has been started, wait until the looper has been created.
    47         synchronized (this) {
    48             while (isAlive() && mLooper == null) {
    49                 try {
    50                     wait();
    51                 } catch (InterruptedException e) {
    52                 }
    53             }
    54         }
    55         return mLooper;
    56     }
    57 
    58 
    59 
    60        public boolean quit() {
    61         Looper looper = getLooper();
    62         if (looper != null) {
    63             looper.quit();
    64             return true;
    65         }
    66         return false;
    67     }
    68 
    69 
    70 
    71 
    72 
    73       public boolean quitSafely() {
    74         Looper looper = getLooper();
    75         if (looper != null) {
    76             looper.quitSafely();
    77             return true;
    78         }
    79         return false;
    80     }
    81 
    82 
    83 
    84 
    85      public int getThreadId() {
    86         return mTid;
    87     }
    88 }

    为了让大家看清楚,我们源码的一些英文注释干掉了,现在就很清晰了。整个类中,除了构造方法和对外提供几个public方法以外,就剩一个方法了run()。从它的实现来看,和普通的Thread实现没有什么区别。都是在run()方法中执行耗时操作。不过,HandlerThread内部创建了消息队列,并且run()方法是一个无限循环的方法,当我们不需要HandlerThread的时候,我们可以调用quitSafely()或者quit()方法来结束这个线程。这是比较方便的。

    2、IntentService

    IntentService是一种特殊的Service,它是Service的子类,并且它是一个抽象类,所以必须创建它的子类才可以使用Intent Service。Intent Service可用于执行后台的耗时任务,当任务执行完毕,它会自己结束,不需要开发着手动结束它。这里需要注意一个问题,Intentservice内置有线程,但是它还是属于Service,所以它的优先级会比线程高很多,所以不容易被系统杀死。所以比较合适去执行一些优先级比较高的任务。看看它的源码:

      1 package android.app;
      2 
      3 import android.annotation.WorkerThread;
      4 import android.annotation.Nullable;
      5 import android.content.Intent;
      6 import android.os.Handler;
      7 import android.os.HandlerThread;
      8 import android.os.IBinder;
      9 import android.os.Looper;
     10 import android.os.Message;
     11 
     12 
     13 
     14 public abstract class IntentService extends Service {
     15     private volatile Looper mServiceLooper;
     16     private volatile ServiceHandler mServiceHandler;
     17     private String mName;
     18     private boolean mRedelivery;
     19 
     20 
     21 
     22     private final class ServiceHandler extends Handler {
     23         public ServiceHandler(Looper looper) {
     24             super(looper);
     25         }
     26 
     27 
     28 
     29         @Override
     30         public void handleMessage(Message msg) {
     31             onHandleIntent((Intent)msg.obj);
     32             stopSelf(msg.arg1);
     33         }
     34     }
     35 
     36 
     37 
     38 
     39     public IntentService(String name) {
     40         super();
     41         mName = name;
     42     }
     43 
     44 
     45 
     46 
     47    public void setIntentRedelivery(boolean enabled) {
     48         mRedelivery = enabled;
     49     }
     50 
     51     @Override
     52     public void onCreate() {
     53         // TODO: It would be nice to have an option to hold a partial wakelock
     54         // during processing, and to have a static startService(Context, Intent)
     55         // method that would launch the service & hand off a wakelock.
     56 
     57         super.onCreate();
     58         HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
     59         thread.start();
     60 
     61         mServiceLooper = thread.getLooper();
     62         mServiceHandler = new ServiceHandler(mServiceLooper);
     63     }
     64 
     65 
     66 
     67 
     68     @Override
     69     public void onStart(@Nullable Intent intent, int startId) {
     70         Message msg = mServiceHandler.obtainMessage();
     71         msg.arg1 = startId;
     72         msg.obj = intent;
     73         mServiceHandler.sendMessage(msg);
     74     }
     75 
     76 
     77 
     78 
     79       @Override
     80     public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
     81         onStart(intent, startId);
     82         return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
     83     }
     84 
     85 
     86 
     87 
     88     @Override
     89     public void onDestroy() {
     90         mServiceLooper.quit();
     91     }
     92 
     93 
     94 
     95 
     96     public IBinder onBind(Intent intent) {
     97         return null;
     98     }
     99 
    100 
    101 
    102 
    103     @WorkerThread
    104     protected abstract void onHandleIntent(@Nullable Intent intent);
    105 }

    这里就很简单了,这些方法对于经常使用Service的朋友来说,就很熟悉了。大家看onCreate()方法。没错IntentService就是封装了HandlerThread和Handler。

    当我们启动IntentService是onCreate(),方法将会被调用,然后就会创建HandlerThread和ServiceHandler。而onStartCommand()方法又调用了onStart()方法,从onStart()方法可以看出IntentService 仅仅是通过ServiceHandler来发一个消息,这个消息会在HandlerThread中被处理掉。

    大家看这个onStart()方法,将intent作为消息传递给onHandleIntent,这个intent通常是我们传递进来的数据。而onHandleIntent就是通过这个intent来区别具体的后台任务的。 

    好了,AsyncTask的使用和工作原理。我们会在下一章在说。下面我们看看线程池吧。

    不知道大家有没有遇到过这种情况。我们在写项目,遇到耗时操作的时候,怎么办呢,是不是new Thread().start,那这样的话,整个项目中得new多少个Thread。这种明显是很浪费性能。毕竟线程也是好资源的嘛。那么有没有一种可以方法对线程进行复用呢?答案就是线程池。

    先说一下线程池的好处:

    1、重用线程池中的线程,避免因为线程的创建和销毁带来的性能开销。

    2、能有效的控制线程池中的线程并发数,避免大量线程之间因为互相抢占资源而导致的阻塞现象。

    3、能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。

    ThreadPoolExecutor

    Android中的线程池概念是来源于java中Executor,Executor是一个空的接口,真正的线程池实现ThreadPoolExecutor。

    1 public ThreadPoolExecutor(int corePoolSize,
    2                               int maximumPoolSize,
    3                               long keepAliveTime,
    4                               TimeUnit unit,
    5                               BlockingQueue<Runnable> workQueue,
    6                               ThreadFactory threadFactory) {
    7         this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
    8              threadFactory, defaultHandler);
    9     }

    简单介绍一下ThreadPoolExcutor各个参数的含义

    corePoolSize:线程池的核心线程数,默认情况下,核心线程会在线程池中一直存活,即使他们处于闲置状态。当我们把ThreadPoolExecutor中的allowCoreThreadTimeOut属性设置为true,那么闲置的核心线程在等待新任务的时候,如果时间超过keepAliveTime所设置的时间,核心线程将会被回收。

    maximumPoolSize:设置最大线程池能够容纳的最大线程数,当线程池中的线程达到这个数以后,新任务将会被阻塞。

    keepAliveTime:非核心线程数闲置的时间。

    unit:指定keepAliveTime参数的时间单位。

    workQueue:线程池中的任务队列。

    threadFactory:线程工厂,为线程池提供创建新线程的功能。

    线程池的分类

    Android中常见的线程池有四种,FixedThreadPool、CachedThreadPool、ScheduledThreadPool、SingleThreadExecutor。

    FixedThreadPool

    FixedThreadPool线程池是通过Executors的new FixedThreadPool方法来创建。它的特点是该线程池中的线程数量是固定的。即使线程处于闲置的状态,它们也不会被回收,除非线程池被关闭。当所有的线程都处于活跃状态的时候,新任务就处于队列中等待线程来处理。注意,FixedThreadPool只有核心线程,没有非核心线程。

    1 public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
    2         return new ThreadPoolExecutor(nThreads, nThreads,
    3                                       0L, TimeUnit.MILLISECONDS,
    4                                       new LinkedBlockingQueue<Runnable>(),
    5                                       threadFactory);
    6     }

    CachedThreadPool

    CachedThreadPool线程池是通过Executors的newCachedThreadPool进行创建的。它是一种线程数目不固定的线程池,它没有核心线程,只有非核心线程,当线程池中的线程都处于活跃状态,就会创建新的线程来处理新的任务。否则就会利用闲置的线程来处理新的任务。线程池中的线程都有超时机制,这个超时机制时长是60s,超过这个时间,闲置的线程就会被回收。这种线程池适合处理大量并且耗时较少的任务。这里得说一下,CachedThreadPool的任务队列,基本都是空的。

    1 public static ExecutorService newCachedThreadPool() {
    2         return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
    3                                       60L, TimeUnit.SECONDS,
    4                                       new SynchronousQueue<Runnable>());
    5     }

    ScheduledThreadPool

    ScheduledThreadPool线程池是通过Executors的newScheduledThreadPool进行创建的,它的核心线程是固定的,但是非核心线程数是不固定的,并且当非核心线程一处于空闲状态,就立即被回收。这种线程适合执行定时任务和具有固定周期的重复任务。

     1 public static ScheduledExecutorService newScheduledThreadPool(
     2             int corePoolSize, ThreadFactory threadFactory) {
     3         return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
     4     }
     5 
     6 
     7 public ScheduledThreadPoolExecutor(int corePoolSize,
     8                                        ThreadFactory threadFactory) {
     9         super(corePoolSize, Integer.MAX_VALUE,
    10               DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
    11               new DelayedWorkQueue(), threadFactory);
    12     }

    SingleThreadExecutor

    SingleThreadExecutor线程池是通过Executors的newSingleThreadExecutor方法来创建的,这类线程池中只有一个核心线程,也没有非核心线程,这就确保了所有任务能够在同一个线程并且按照顺序来执行,这样就不需要考虑线程同步的问题。

     1 public static ExecutorService newSingleThreadExecutor() {
     2 
     3         return new FinalizableDelegatedExecutorService
     4 
     5             (new ThreadPoolExecutor(1, 1,
     6 
     7                                     0L, TimeUnit.MILLISECONDS,
     8 
     9                                     new LinkedBlockingQueue<Runnable>()));
    10 
    11     }

    好了,写了这么多,真特么累,下部分就和大家分享一下AsyncTask的 工作原理。

  • 相关阅读:
    2.4.6 处理表单 的 工作原理的解释
    nginx proxy模块
    nginx负载均衡模块
    Oracle正在执行和执行过的SQL语句
    nginx
    linux :故障提示:Error:No suitable device found: no device found for connection "System eth0"
    memcached
    一致性哈希算法(consistent hashing)(转)
    大规模网站sesson会话保持思路及实践配置
    AB压力测试工具
  • 原文地址:https://www.cnblogs.com/huangjialin/p/8546513.html
Copyright © 2011-2022 走看看