zoukankan      html  css  js  c++  java
  • Android 线程与消息 机制 15问15答

    1.handler,looper,messagequeue三者之间的关系以及各自的角色?

    答:MessageQueue就是存储消息的载体,Looper就是无限循环查找这个载体里是否还有消息。Handler就是创建的时候 会使用looper来构建这个消息循环。

    handler的主要功能就是 将一个任务切换到某个指定的线程中去执行。

    2.为何android 无法在子线程更新ui?

    答:都知道 更新ui 实际工作都是在viewrootimpl这个类里面去做的。他的源码里有下面这样一个函数:

    1   void checkThread() {
    2         if (mThread != Thread.currentThread()) {
    3             throw new CalledFromWrongThreadException(
    4                     "Only the original thread that created a view hierarchy can touch its views.");
    5         }
    6     }
    View Code

    在源码里 就限定了 你这个子线程是不能访问ui的。只有主线程能访问ui。原因其实很简单,你要是允许子线程也操作ui,那就得给ui 加上锁机制,

    锁机制就太影响效率了。所以为了效率 就控制开发者 只能在主线程上访问ui。

    3.简单概述一下Handler的工作原理?

    答:其实很简单,关系理顺了就可以了。首先要明白 handler要创建成功 必须有一个前提条件 就是创建handler的线程 必须有looper。不然就会报错。

      handler使用方法 一般就2个 post 传一个runnable 或者send一个消息。注意的是post方法 最后其实也是调用的send方法。这个send方法

      最终会调用messagequeue的enqueuemessage方法,就是把消息放入队列中。与此同时looper 是一个无限循环 会无限从这个消息队列里面

         取消息,取出来以后 消息中的runnable 或者 handler的handlerMessage方法就会被调用了。这个地方有一个关键的地方就在于 我们的looper

         是运行在 创建handler的线程中的。所以looper在处理消息的时候 会把这个消息也运行在 创建handler的所在线程中。想明白这点 就明白了

      handler的运行机制了。

    4.简单介绍下threadLocal?

    答:这个东西 在looper activitythread 以及ams中 都有大量应用。其实作用就是在指定的线程中存储数据。当你希望有一个数据 在不同线程中 都能独立保存自己的独立值

    互相不干扰互相不影响的时候 就可以使用threadlocal了。他的作用域仅限于线程。

    给个例子

     1 package com.example;
     2 
     3 public class MyClass {
     4 
     5 
     6     public static void main(String[] args) {
     7 
     8         ThreadLocal<Integer> mIntegerThreadLocal = new ThreadLocal<Integer>();
     9         mIntegerThreadLocal.set(0);
    10         //输出结果为main thread threadlocal==0
    11         System.out.println("main thread threadlocal==" + mIntegerThreadLocal.get());
    12 
    13         new Thread("Thread 1") {
    14             @Override
    15             public void run() {
    16                 mIntegerThreadLocal.set(0);
    17                 mIntegerThreadLocal.set(mIntegerThreadLocal.get() + 2);
    18                 //输出结果为 Thread 1 threadlocal==2
    19                 System.out.println("Thread 1 threadlocal==" + mIntegerThreadLocal.get());
    20             }
    21         }.start();
    22 
    23         new Thread("Thread 2") {
    24             @Override
    25             public void run() {
    26                 //这里就会报空指针错误了 因为mIntegerThreadLocal 在这个线程中没有初始化他的值所以是null pointer
    27                 mIntegerThreadLocal.set(mIntegerThreadLocal.get() + 2);
    28                 System.out.println("Thread 1 threadlocal==" + mIntegerThreadLocal.get());
    29             }
    30         }.start();
    31 
    32 
    33     }
    34 }
    View Code

    5.从源码的角度 阐述threadlocal的原理?

    答:

      1 //首先我们可以看到 这是一个泛型, 我们的分析 建立在java 1.8 的基础上 其他java版本这里实现都有各自的不同 有兴趣的可以自己自行分析
      2 public class ThreadLocal<T> {
      3 
      4 //然后我们看一下 set方法
      5 public void set(T value) {
      6         //先取出当前的thread
      7         Thread t = Thread.currentThread();
      8         //然后从getMap方法里 取t 也就是当前这个thread的数据 , ThreadLocalMap是一个静态内部类 你可以把他看做 存储threadlocal数据的一个载体
      9         ThreadLocalMap map = getMap(t);
     10         //如果取出来是空 那就给他set一个值进去 也就是更新这个threadlocal的值
     11         if (map != null)
     12             map.set(this, value);
     13         else
     14             //否则就创建一个ThreadLocalMap的值
     15             createMap(t, value);
     16     }
     17 
     18 //getMap就是取出这个线程的threadLocals 如果这个值为null 就说明这个线程还从来没有使用过threadlocal对象
     19 ThreadLocalMap getMap(Thread t) {
     20         return t.threadLocals;
     21     }
     22 
     23 
     24 
     25 //我们可以先跟踪createMap方法 也就是创建ThreadLocalMap的流程
     26 void createMap(Thread t, T firstValue) {
     27         //这里thread的threadLocals 的值 就是在这里被赋值了,也就是ThreadLocalMap对象
     28         //可以明确 一个线程T,就有一个唯一的ThreadLocalMap对象,里面存储的就是
     29         //这个线程里的th对象。也就是threadlocal
     30         t.threadLocals = new ThreadLocalMap(this, firstValue);
     31 }
     32 
     33 //可以看到是用这个构造方法来构造的
     34  ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
     35             //首先是创造了一个table数组
     36             table = new Entry[INITIAL_CAPACITY];
     37             //然后根据一定的算法 计算出来 我们传进来的这个ThreadLocal 应该在table数组里的位置 也就是i
     38             int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
     39             //然后把i位置上对应的值 赋值进去,有点类似于hashmap的流程 
     40             table[i] = new Entry(firstKey, firstValue);
     41             size = 1;
     42             setThreshold(INITIAL_CAPACITY);
     43             //所以这里要明确的就是一个th的值 在table数组里 就对应着一个位置,
     44   }
     45 
     46 
     47 
     48 //简单浏览一下Entry的数据结构
     49         static class Entry extends WeakReference<ThreadLocal<?>> {
     50             /** The value associated with this ThreadLocal. */
     51             Object value;
     52 
     53             Entry(ThreadLocal<?> k, Object v) {
     54                 super(k);
     55                 value = v;
     56             }
     57         }
     58 
     59 
     60 
     61 
     62 //前面我们简单分析了 threadlocal 第一次被创建时的 存储过程
     63 //然后看我们的set方法 也就是更新threadlocal的过程
     64 //这里的逻辑很简单  当某个线程t 已经有了threadLocals的值以后 第二次再调用set方法 就会走到这里了。第一次调用set方法 可以看上面的createMap流程
     65 //当第二次或者第n次调用set方法 以后 就会根据th的值 在table里遍历 找到这个th对应的值,因为一个线程t 可能有n个不同的th变量。
     66 //这个函数就是根据你传进去的th变量 找到对应的位置 来更新他的值
     67  private void set(ThreadLocal<?> key, Object value) {
     68 
     69             // We don't use a fast path as with get() because it is at
     70             // least as common to use set() to create new entries as
     71             // it is to replace existing ones, in which case, a fast
     72             // path would fail more often than not.
     73 
     74             Entry[] tab = table;
     75             int len = tab.length;
     76             //通过我们传进去的theradlocal 取出table数组里的值 table[i]
     77             int i = key.threadLocalHashCode & (len-1);
     78 
     79             
     80             for (Entry e = tab[i];
     81                  e != null;
     82                  e = tab[i = nextIndex(i, len)]) {
     83                 ThreadLocal<?> k = e.get();
     84 
     85                 if (k == key) {
     86                     e.value = value;
     87                     return;
     88                 }
     89 
     90                 if (k == null) {
     91                     replaceStaleEntry(key, value, i);
     92                     return;
     93                 }
     94             }
     95 
     96             tab[i] = new Entry(key, value);
     97             int sz = ++size;
     98             if (!cleanSomeSlots(i, sz) && sz >= threshold)
     99                 rehash();
    100         }
    101 
    102 
    103 //再来看一下 threadlocal的get方法
    104 public T get() {
    105         Thread t = Thread.currentThread();
    106         //先看看当前线程t的threadLocals 有没有被赋值
    107         ThreadLocalMap map = getMap(t);
    108         //如果不等于null 也就是说当前线程的threadLocals 值已经有了 那我们就直接取对应的value值即可
    109         if (map != null) {
    110             ThreadLocalMap.Entry e = map.getEntry(this);
    111             if (e != null) {
    112                 @SuppressWarnings("unchecked")
    113                 T result = (T)e.value;
    114                 return result;
    115             }
    116         }
    117         //否则我们就给他返回一个初始值 这个初始值 你跟进去看源码就会发现是null了
    118         return setInitialValue();
    119     }
    120 
    121   //简单分析了 threadlocal 的set和get方法 总结起来就是 他的set和get操作 就是以当前线程为key 取对应的值。可以简单类比想象成是一个哈希表 这个哈希表的key就是线程。
    122   //你要操作th的值 就得把当前的线程t 传到这个表里面 然后取得对应线程t的 对应value 即可。
    View Code

    6.从源码的角度 阐述MessageQueue的原理?

    答:

      1  //我们首先来看一下enqueueMessage的操作 这个操作主要是对消息队列进行一个插入消息的操作
      2  //这个你细细看一下 就是一个很简单的单链表的操作罢了,随意虽然这东西 叫消息队列 但是其实跟队列并没有什么关系
      3  //内部实现为一个链表 
      4  boolean enqueueMessage(Message msg, long when) {
      5         if (msg.target == null) {
      6             throw new IllegalArgumentException("Message must have a target.");
      7         }
      8         if (msg.isInUse()) {
      9             throw new IllegalStateException(msg + " This message is already in use.");
     10         }
     11 
     12         synchronized (this) {
     13             if (mQuitting) {
     14                 IllegalStateException e = new IllegalStateException(
     15                         msg.target + " sending message to a Handler on a dead thread");
     16                 Log.w(TAG, e.getMessage(), e);
     17                 msg.recycle();
     18                 return false;
     19             }
     20 
     21             msg.markInUse();
     22             msg.when = when;
     23             //mMessages 这个你可以把他看成是单链表的表头
     24             Message p = mMessages;
     25             boolean needWake;
     26             //当你第一次往消息队列里 插入消息的时候,表头就变成了你第一次传进来的这个消息
     27             if (p == null || when == 0 || when < p.when) {
     28                 // New head, wake up the event queue if blocked.
     29                 msg.next = p;
     30                 mMessages = msg;
     31                 needWake = mBlocked;
     32             } else {
     33                 // Inserted within the middle of the queue.  Usually we don't have to wake
     34                 // up the event queue unless there is a barrier at the head of the queue
     35                 // and the message is the earliest asynchronous message in the queue.
     36                 needWake = mBlocked && p.target == null && msg.isAsynchronous();
     37 
     38                 //如果不是第一次传消息  
     39                 //简单的链表操作不多做分析
     40                 Message prev;
     41                 for (;;) {
     42                     prev = p;
     43                     p = p.next;
     44                     if (p == null || when < p.when) {
     45                         break;
     46                     }
     47                     if (needWake && p.isAsynchronous()) {
     48                         needWake = false;
     49                     }
     50                 }
     51                 msg.next = p; // invariant: p == prev.next
     52                 prev.next = msg;
     53             }
     54 
     55             // We can assume mPtr != 0 because mQuitting is false.
     56             if (needWake) {
     57                 nativeWake(mPtr);
     58             }
     59         }
     60         return true;
     61     }
     62 
     63 
     64 //next方法就是从消息队列中 取出一个消息 然后删除他
     65      Message next() {
     66         // Return here if the message loop has already quit and been disposed.
     67         // This can happen if the application tries to restart a looper after quit
     68         // which is not supported.
     69         final long ptr = mPtr;
     70         if (ptr == 0) {
     71             return null;
     72         }
     73 
     74         int pendingIdleHandlerCount = -1; // -1 only during first iteration
     75         int nextPollTimeoutMillis = 0;
     76         //注意看这个for循环 括号体内是没有break语句的 也就是说这个循环 永远不会退出!如果这个消息队列里没有消息的话
     77         //这个next方法 就阻塞了 因为你仔细看 这个里面没有break语句 只有当取出消息的时候才会return一个message回去
     78         //只有这种情况成立的时候 这个循环才会结束 这个函数才会结束,除此之外 这个函数就永远阻塞在这里
     79         for (;;) {
     80             if (nextPollTimeoutMillis != 0) {
     81                 Binder.flushPendingCommands();
     82             }
     83 
     84             nativePollOnce(ptr, nextPollTimeoutMillis);
     85 
     86             synchronized (this) {
     87                 // Try to retrieve the next message.  Return if found.
     88                 final long now = SystemClock.uptimeMillis();
     89                 Message prevMsg = null;
     90                 Message msg = mMessages;
     91                 if (msg != null && msg.target == null) {
     92                     // Stalled by a barrier.  Find the next asynchronous message in the queue.
     93                     do {
     94                         prevMsg = msg;
     95                         msg = msg.next;
     96                     } while (msg != null && !msg.isAsynchronous());
     97                 }
     98                 if (msg != null) {
     99                     if (now < msg.when) {
    100                         // Next message is not ready.  Set a timeout to wake up when it is ready.
    101                         nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
    102                     } else {
    103                         // Got a message.
    104                         mBlocked = false;
    105                         if (prevMsg != null) {
    106                             prevMsg.next = msg.next;
    107                         } else {
    108                             mMessages = msg.next;
    109                         }
    110                         msg.next = null;
    111                         if (DEBUG) Log.v(TAG, "Returning message: " + msg);
    112                         msg.markInUse();
    113                         return msg;
    114                     }
    115                 } else {
    116                     // No more messages.
    117                     nextPollTimeoutMillis = -1;
    118                 }
    119 
    120                 // Process the quit message now that all pending messages have been handled.
    121                 if (mQuitting) {
    122                     dispose();
    123                     return null;
    124                 }
    125 
    126                 // If first time idle, then get the number of idlers to run.
    127                 // Idle handles only run if the queue is empty or if the first message
    128                 // in the queue (possibly a barrier) is due to be handled in the future.
    129                 if (pendingIdleHandlerCount < 0
    130                         && (mMessages == null || now < mMessages.when)) {
    131                     pendingIdleHandlerCount = mIdleHandlers.size();
    132                 }
    133                 if (pendingIdleHandlerCount <= 0) {
    134                     // No idle handlers to run.  Loop and wait some more.
    135                     mBlocked = true;
    136                     continue;
    137                 }
    138 
    139                 if (mPendingIdleHandlers == null) {
    140                     mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
    141                 }
    142                 mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
    143             }
    144 
    145             // Run the idle handlers.
    146             // We only ever reach this code block during the first iteration.
    147             for (int i = 0; i < pendingIdleHandlerCount; i++) {
    148                 final IdleHandler idler = mPendingIdleHandlers[i];
    149                 mPendingIdleHandlers[i] = null; // release the reference to the handler
    150 
    151                 boolean keep = false;
    152                 try {
    153                     keep = idler.queueIdle();
    154                 } catch (Throwable t) {
    155                     Log.wtf(TAG, "IdleHandler threw exception", t);
    156                 }
    157 
    158                 if (!keep) {
    159                     synchronized (this) {
    160                         mIdleHandlers.remove(idler);
    161                     }
    162                 }
    163             }
    164 
    165             // Reset the idle handler count to 0 so we do not run them again.
    166             pendingIdleHandlerCount = 0;
    167 
    168             // While calling an idle handler, a new message could have been delivered
    169             // so go back and look again for a pending message without waiting.
    170             nextPollTimeoutMillis = 0;
    171         }
    172     }
    View Code

    7.从源码的角度 阐述Looper的原理?

    答:

     1 //这是一个典型的在子线程里创建handler的操作 我们看到在这里创建handler的时候 我们做了2步操作
     2 //第一步是创建looper 第二步是开启消息循环。
     3         new Thread(){
     4             @Override
     5             public void run() {
     6                Looper.prepare();
     7                 Handler handler=new Handler();
     8                 Looper.loop();
     9             }
    10         }.start();
    11 
    12 
    13 //我们主要看loop 这个方法 因为只有调用了这个方法 消息循环才真正启动
    14 
    15  public static void loop() {
    16         final Looper me = myLooper();
    17         if (me == null) {
    18             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    19         }
    20         final MessageQueue queue = me.mQueue;
    21 
    22         // Make sure the identity of this thread is that of the local process,
    23         // and keep track of what that identity token actually is.
    24         Binder.clearCallingIdentity();
    25         final long ident = Binder.clearCallingIdentity();
    26         //可以看到 这又是一个死循环
    27         for (;;) {
    28             Message msg = queue.next(); // might block
    29             //唯一跳出循环的方式 就是这个msg 为null 也就是消息队列的next方法返回null
    30             //而next方法返回null的唯一方法 就是调用looper的quit方法 所以这里就能得知
    31             //looper你必须手动帮他退出 否则loop方法就是无限循环下去
    32             if (msg == null) {
    33                 // No message indicates that the message queue is quitting.
    34                 return;
    35             }
    36 
    37             // This must be in a local variable, in case a UI event sets the logger
    38             Printer logging = me.mLogging;
    39             if (logging != null) {
    40                 logging.println(">>>>> Dispatching to " + msg.target + " " +
    41                         msg.callback + ": " + msg.what);
    42             }
    43 
    44             //这个地方msg 就是发过来的消息,也就是消息队列那个链表里面存储的message ,target就是发送这条消息的handler对象。
    45             //所以这里就能明白最终消息 还是交给handler的dispatchmessage方法来处理的 只不过这个dispatchmessage方法 是在创建handler
    46             //的时候 所使用的looper去执行的 而我们创建looper的时机 正是在线程的run方法里,所以 代码逻辑的最终执行就是在创建handler
    47             //的那个线程里
    48             msg.target.dispatchMessage(msg);
    49 
    50             if (logging != null) {
    51                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
    52             }
    53 
    54             // Make sure that during the course of dispatching the
    55             // identity of the thread wasn't corrupted.
    56             final long newIdent = Binder.clearCallingIdentity();
    57             if (ident != newIdent) {
    58                 Log.wtf(TAG, "Thread identity changed from 0x"
    59                         + Long.toHexString(ident) + " to 0x"
    60                         + Long.toHexString(newIdent) + " while dispatching to "
    61                         + msg.target.getClass().getName() + " "
    62                         + msg.callback + " what=" + msg.what);
    63             }
    64 
    65             msg.recycleUnchecked();
    66         }
    67     }
    View Code

    8.使用looper需要注意什么?

    答:不需要的时候 记得终止looper。因为如果你手动处理完毕你需要的业务逻辑以后 如果不调用quit或者quitsafely方法 looper的loop方法就一直执行下去,永远不停止,你这个子线程永远都结束不了。

    很容易就内存泄露 或者其他错误,所以我们要牢记 当子线程使用looper的时候 业务处理完毕 记得手动关闭looper。

    9.从源码的角度 阐述handler的工作原理?

    答:

     1  //handler有2个发消息的方法一个是post 一个是send 只不过post最终也是走的send
     2  //可以看出来 handler发送消息 其实就是往消息队列里放了一个message罢了
     3  public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
     4         MessageQueue queue = mQueue;
     5         if (queue == null) {
     6             RuntimeException e = new RuntimeException(
     7                     this + " sendMessageAtTime() called with no mQueue");
     8             Log.w("Looper", e.getMessage(), e);
     9             return false;
    10         }
    11         return enqueueMessage(queue, msg, uptimeMillis);
    12     }
    13 
    14 
    15 
    16     //这是handler处理消息的逻辑 注意这个方法的执行 实在looper所属的线程中。
    17     public void dispatchMessage(Message msg) {
    18     //msg的callback就是runnable对象
    19         if (msg.callback != null) {
    20           //如果你是post方法 实际上handler就是调用你post传进去的那个runnable的run方法而已。
    21             handleCallback(msg);
    22         } else {
    23             //这个实际上就是提供一个 不用派生handler子类时 创建handler对象的方法 虽然我们实际使用中很少使用这种方式
    24             if (mCallback != null) {
    25                 if (mCallback.handleMessage(msg)) {
    26                     return;
    27                 }
    28             }
    29             handleMessage(msg);
    30         }
    31     }
    32 
    33 
    34     private static void handleCallback(Message message) {
    35         message.callback.run();
    36     }
    37 
    38     public interface Callback {
    39         public boolean handleMessage(Message msg);
    40     }
    41 
    42 
    43 
    44 
    45 //看这个构造函数 就能明白为啥创建handler的时候必须得有looper了 所以再一次强调
    46 //在子线程中创建handler的前提条件 是一定得有looper,
    47     public Handler(Callback callback, boolean async) {
    48         if (FIND_POTENTIAL_LEAKS) {
    49             final Class<? extends Handler> klass = getClass();
    50             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
    51                     (klass.getModifiers() & Modifier.STATIC) == 0) {
    52                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
    53                     klass.getCanonicalName());
    54             }
    55         }
    56 
    57         mLooper = Looper.myLooper();
    58         if (mLooper == null) {
    59             throw new RuntimeException(
    60                 "Can't create handler inside thread that has not called Looper.prepare()");
    61         }
    62         mQueue = mLooper.mQueue;
    63         mCallback = callback;
    64         mAsynchronous = async;
    65     }
    View Code

    10.android里 主线程的消息循环是怎样实现的?

    答:

      1  
      2 //可以看activitythread 的源码
      3  public static void main(String[] args) {
      4         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
      5         SamplingProfilerIntegration.start();
      6         // CloseGuard defaults to true and can be quite spammy.  We
      7         // disable it here, but selectively enable it later (via
      8         // StrictMode) on debug builds, but using DropBox, not logs.
      9         CloseGuard.setEnabled(false);
     10         Environment.initForCurrentUser();
     11         // Set the reporter for event logging in libcore
     12         EventLogger.setReporter(new EventLoggingReporter());
     13         AndroidKeyStoreProvider.install();
     14         // Make sure TrustedCertificateStore looks in the right place for CA certificates
     15         final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
     16         TrustedCertificateStore.setDefaultUserDirectory(configDir);
     17         Process.setArgV0("<pre-initialized>");
     18         //创建了主线程的looper
     19         Looper.prepareMainLooper();
     20         ActivityThread thread = new ActivityThread();
     21         thread.attach(false);
     22         if (sMainThreadHandler == null) {
     23             sMainThreadHandler = thread.getHandler();
     24         }
     25         if (false) {
     26             Looper.myLooper().setMessageLogging(new
     27                     LogPrinter(Log.DEBUG, "ActivityThread"));
     28         }
     29         // End of event ActivityThreadMain.
     30         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     31         //开启了主线程的消息循环
     32         Looper.loop();
     33         throw new RuntimeException("Main thread loop unexpectedly exited");
     34     }
     35 }
     36 
     37 //这个就是主线程 的handler 四大组件的启动 停止过程 都在这个里面定义好了
     38 
     39 private class H extends Handler {
     40         public static final int LAUNCH_ACTIVITY         = 100;
     41         public static final int PAUSE_ACTIVITY          = 101;
     42         public static final int PAUSE_ACTIVITY_FINISHING= 102;
     43         public static final int STOP_ACTIVITY_SHOW      = 103;
     44         public static final int STOP_ACTIVITY_HIDE      = 104;
     45         public static final int SHOW_WINDOW             = 105;
     46         public static final int HIDE_WINDOW             = 106;
     47         public static final int RESUME_ACTIVITY         = 107;
     48         public static final int SEND_RESULT             = 108;
     49         public static final int DESTROY_ACTIVITY        = 109;
     50         public static final int BIND_APPLICATION        = 110;
     51         public static final int EXIT_APPLICATION        = 111;
     52         public static final int NEW_INTENT              = 112;
     53         public static final int RECEIVER                = 113;
     54         public static final int CREATE_SERVICE          = 114;
     55         public static final int SERVICE_ARGS            = 115;
     56         public static final int STOP_SERVICE            = 116;
     57         public static final int CONFIGURATION_CHANGED   = 118;
     58         public static final int CLEAN_UP_CONTEXT        = 119;
     59         public static final int GC_WHEN_IDLE            = 120;
     60         public static final int BIND_SERVICE            = 121;
     61         public static final int UNBIND_SERVICE          = 122;
     62         public static final int DUMP_SERVICE            = 123;
     63         public static final int LOW_MEMORY              = 124;
     64         public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
     65         public static final int RELAUNCH_ACTIVITY       = 126;
     66         public static final int PROFILER_CONTROL        = 127;
     67         public static final int CREATE_BACKUP_AGENT     = 128;
     68         public static final int DESTROY_BACKUP_AGENT    = 129;
     69         public static final int SUICIDE                 = 130;
     70         public static final int REMOVE_PROVIDER         = 131;
     71         public static final int ENABLE_JIT              = 132;
     72         public static final int DISPATCH_PACKAGE_BROADCAST = 133;
     73         public static final int SCHEDULE_CRASH          = 134;
     74         public static final int DUMP_HEAP               = 135;
     75         public static final int DUMP_ACTIVITY           = 136;
     76         public static final int SLEEPING                = 137;
     77         public static final int SET_CORE_SETTINGS       = 138;
     78         public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
     79         public static final int TRIM_MEMORY             = 140;
     80         public static final int DUMP_PROVIDER           = 141;
     81         public static final int UNSTABLE_PROVIDER_DIED  = 142;
     82         public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
     83         public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
     84         public static final int INSTALL_PROVIDER        = 145;
     85         public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
     86         public static final int CANCEL_VISIBLE_BEHIND = 147;
     87         public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148;
     88         public static final int ENTER_ANIMATION_COMPLETE = 149;
     89         String codeToString(int code) {
     90             if (DEBUG_MESSAGES) {
     91                 switch (code) {
     92                     case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
     93                     case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
     94                     case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
     95                     case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
     96                     case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
     97                     case SHOW_WINDOW: return "SHOW_WINDOW";
     98                     case HIDE_WINDOW: return "HIDE_WINDOW";
     99                     case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
    100                     case SEND_RESULT: return "SEND_RESULT";
    101                     case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
    102                     case BIND_APPLICATION: return "BIND_APPLICATION";
    103                     case EXIT_APPLICATION: return "EXIT_APPLICATION";
    104                     case NEW_INTENT: return "NEW_INTENT";
    105                     case RECEIVER: return "RECEIVER";
    106                     case CREATE_SERVICE: return "CREATE_SERVICE";
    107                     case SERVICE_ARGS: return "SERVICE_ARGS";
    108                     case STOP_SERVICE: return "STOP_SERVICE";
    109                     case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
    110                     case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
    111                     case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
    112                     case BIND_SERVICE: return "BIND_SERVICE";
    113                     case UNBIND_SERVICE: return "UNBIND_SERVICE";
    114                     case DUMP_SERVICE: return "DUMP_SERVICE";
    115                     case LOW_MEMORY: return "LOW_MEMORY";
    116                     case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
    117                     case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
    118                     case PROFILER_CONTROL: return "PROFILER_CONTROL";
    119                     case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
    120                     case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
    121                     case SUICIDE: return "SUICIDE";
    122                     case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
    123                     case ENABLE_JIT: return "ENABLE_JIT";
    124                     case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
    125                     case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
    126                     case DUMP_HEAP: return "DUMP_HEAP";
    127                     case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
    128                     case SLEEPING: return "SLEEPING";
    129                     case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
    130                     case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
    131                     case TRIM_MEMORY: return "TRIM_MEMORY";
    132                     case DUMP_PROVIDER: return "DUMP_PROVIDER";
    133                     case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
    134                     case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS";
    135                     case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE";
    136                     case INSTALL_PROVIDER: return "INSTALL_PROVIDER";
    137                     case ON_NEW_ACTIVITY_OPTIONS: return "ON_NEW_ACTIVITY_OPTIONS";
    138                     case CANCEL_VISIBLE_BEHIND: return "CANCEL_VISIBLE_BEHIND";
    139                     case BACKGROUND_VISIBLE_BEHIND_CHANGED: return "BACKGROUND_VISIBLE_BEHIND_CHANGED";
    140                     case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE";
    141                 }
    142             }
    143             return Integer.toString(code);
    144         }
    145         public void handleMessage(Message msg) {
    146             if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    147             switch (msg.what) {
    148                 case LAUNCH_ACTIVITY: {
    149                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    150                     final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
    151                     r.packageInfo = getPackageInfoNoCheck(
    152                             r.activityInfo.applicationInfo, r.compatInfo);
    153                     handleLaunchActivity(r, null);
    154                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    155                 } break;
    156                 case RELAUNCH_ACTIVITY: {
    157                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
    158                     ActivityClientRecord r = (ActivityClientRecord)msg.obj;
    159                     handleRelaunchActivity(r);
    160                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    161                 } break;
    162                 case PAUSE_ACTIVITY:
    163                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
    164                     handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
    165                             (msg.arg1&2) != 0);
    166                     maybeSnapshot();
    167                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    168                     break;
    169                 case PAUSE_ACTIVITY_FINISHING:
    170                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
    171                     handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2,
    172                             (msg.arg1&1) != 0);
    173                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    174                     break;
    175                 case STOP_ACTIVITY_SHOW:
    176                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
    177                     handleStopActivity((IBinder)msg.obj, true, msg.arg2);
    178                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    179                     break;
    180                 case STOP_ACTIVITY_HIDE:
    181                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
    182                     handleStopActivity((IBinder)msg.obj, false, msg.arg2);
    183                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    184                     break;
    185                 case SHOW_WINDOW:
    186                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
    187                     handleWindowVisibility((IBinder)msg.obj, true);
    188                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    189                     break;
    190                 case HIDE_WINDOW:
    191                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
    192                     handleWindowVisibility((IBinder)msg.obj, false);
    193                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    194                     break;
    195                 case RESUME_ACTIVITY:
    196                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
    197                     handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true);
    198                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    199                     break;
    200                 case SEND_RESULT:
    201                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
    202                     handleSendResult((ResultData)msg.obj);
    203                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    204                     break;
    205                 case DESTROY_ACTIVITY:
    206                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
    207                     handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
    208                             msg.arg2, false);
    209                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    210                     break;
    211                 case BIND_APPLICATION:
    212                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
    213                     AppBindData data = (AppBindData)msg.obj;
    214                     handleBindApplication(data);
    215                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    216                     break;
    217                 case EXIT_APPLICATION:
    218                     if (mInitialApplication != null) {
    219                         mInitialApplication.onTerminate();
    220                     }
    221                     Looper.myLooper().quit();
    222                     break;
    223                 case NEW_INTENT:
    224                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
    225                     handleNewIntent((NewIntentData)msg.obj);
    226                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    227                     break;
    228                 case RECEIVER:
    229                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
    230                     handleReceiver((ReceiverData)msg.obj);
    231                     maybeSnapshot();
    232                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    233                     break;
    234                 case CREATE_SERVICE:
    235                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
    236                     handleCreateService((CreateServiceData)msg.obj);
    237                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    238                     break;
    239                 case BIND_SERVICE:
    240                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
    241                     handleBindService((BindServiceData)msg.obj);
    242                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    243                     break;
    244                 case UNBIND_SERVICE:
    245                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
    246                     handleUnbindService((BindServiceData)msg.obj);
    247                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    248                     break;
    249                 case SERVICE_ARGS:
    250                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
    251                     handleServiceArgs((ServiceArgsData)msg.obj);
    252                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    253                     break;
    254                 case STOP_SERVICE:
    255                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
    256                     handleStopService((IBinder)msg.obj);
    257                     maybeSnapshot();
    258                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    259                     break;
    260                 case CONFIGURATION_CHANGED:
    261                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
    262                     mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
    263                     handleConfigurationChanged((Configuration)msg.obj, null);
    264                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    265                     break;
    266                 case CLEAN_UP_CONTEXT:
    267                     ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
    268                     cci.context.performFinalCleanup(cci.who, cci.what);
    269                     break;
    270                 case GC_WHEN_IDLE:
    271                     scheduleGcIdler();
    272                     break;
    273                 case DUMP_SERVICE:
    274                     handleDumpService((DumpComponentInfo)msg.obj);
    275                     break;
    276                 case LOW_MEMORY:
    277                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
    278                     handleLowMemory();
    279                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    280                     break;
    281                 case ACTIVITY_CONFIGURATION_CHANGED:
    282                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
    283                     handleActivityConfigurationChanged((ActivityConfigChangeData)msg.obj);
    284                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    285                     break;
    286                 case PROFILER_CONTROL:
    287                     handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2);
    288                     break;
    289                 case CREATE_BACKUP_AGENT:
    290                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
    291                     handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
    292                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    293                     break;
    294                 case DESTROY_BACKUP_AGENT:
    295                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
    296                     handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
    297                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    298                     break;
    299                 case SUICIDE:
    300                     Process.killProcess(Process.myPid());
    301                     break;
    302                 case REMOVE_PROVIDER:
    303                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
    304                     completeRemoveProvider((ProviderRefCount)msg.obj);
    305                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    306                     break;
    307                 case ENABLE_JIT:
    308                     ensureJitEnabled();
    309                     break;
    310                 case DISPATCH_PACKAGE_BROADCAST:
    311                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
    312                     handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
    313                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    314                     break;
    315                 case SCHEDULE_CRASH:
    316                     throw new RemoteServiceException((String)msg.obj);
    317                 case DUMP_HEAP:
    318                     handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
    319                     break;
    320                 case DUMP_ACTIVITY:
    321                     handleDumpActivity((DumpComponentInfo)msg.obj);
    322                     break;
    323                 case DUMP_PROVIDER:
    324                     handleDumpProvider((DumpComponentInfo)msg.obj);
    325                     break;
    326                 case SLEEPING:
    327                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
    328                     handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
    329                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    330                     break;
    331                 case SET_CORE_SETTINGS:
    332                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
    333                     handleSetCoreSettings((Bundle) msg.obj);
    334                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    335                     break;
    336                 case UPDATE_PACKAGE_COMPATIBILITY_INFO:
    337                     handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
    338                     break;
    339                 case TRIM_MEMORY:
    340                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
    341                     handleTrimMemory(msg.arg1);
    342                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    343                     break;
    344                 case UNSTABLE_PROVIDER_DIED:
    345                     handleUnstableProviderDied((IBinder)msg.obj, false);
    346                     break;
    347                 case REQUEST_ASSIST_CONTEXT_EXTRAS:
    348                     handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
    349                     break;
    350                 case TRANSLUCENT_CONVERSION_COMPLETE:
    351                     handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
    352                     break;
    353                 case INSTALL_PROVIDER:
    354                     handleInstallProvider((ProviderInfo) msg.obj);
    355                     break;
    356                 case ON_NEW_ACTIVITY_OPTIONS:
    357                     Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj;
    358                     onNewActivityOptions(pair.first, pair.second);
    359                     break;
    360                 case CANCEL_VISIBLE_BEHIND:
    361                     handleCancelVisibleBehind((IBinder) msg.obj);
    362                     break;
    363                 case BACKGROUND_VISIBLE_BEHIND_CHANGED:
    364                     handleOnBackgroundVisibleBehindChanged((IBinder) msg.obj, msg.arg1 > 0);
    365                     break;
    366                 case ENTER_ANIMATION_COMPLETE:
    367                     handleEnterAnimationComplete((IBinder) msg.obj);
    368                     break;
    369             }
    370             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
    371         }
    372         private void maybeSnapshot() {
    373             if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) {
    374                 // convert the *private* ActivityThread.PackageInfo to *public* known
    375                 // android.content.pm.PackageInfo
    376                 String packageName = mBoundApplication.info.mPackageName;
    377                 android.content.pm.PackageInfo packageInfo = null;
    378                 try {
    379                     Context context = getSystemContext();
    380                     if(context == null) {
    381                         Log.e(TAG, "cannot get a valid context");
    382                         return;
    383                     }
    384                     PackageManager pm = context.getPackageManager();
    385                     if(pm == null) {
    386                         Log.e(TAG, "cannot get a valid PackageManager");
    387                         return;
    388                     }
    389                     packageInfo = pm.getPackageInfo(
    390                             packageName, PackageManager.GET_ACTIVITIES);
    391                 } catch (NameNotFoundException e) {
    392                     Log.e(TAG, "cannot get package info for " + packageName, e);
    393                 }
    394                 SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo);
    395             }
    396         }
    397     }
    View Code

    11.android sdk中都提供了哪些类 扮演着线程的角色?

    答:主要是asynctask intentservice 以及handlerthread。其中前者的核心是线程池,后两者的实现核心是线程。intentservice 讲白了就是一个后台线程

    只不过这个线程扮演了service的角色 让系统不会轻易的杀死这个线程而已。

    12.使用asynctask有哪些注意事项?

    答:asynctask的源码分析 我以前写过 这里就不多说了,http://www.cnblogs.com/punkisnotdead/p/4469612.html 可以参考。

          主要就是不同版本 asynctask 内部实现不一样。 特别耗时的任务 我们不要放在asynctask 这里做。

      使用要点:

          1.asynctask 要在ui线程也就是主线程创建

      2.execute也要在ui线程执行

      3.一个asynctask只能执行一次execute方法。

      4.3.0以后的android版本 asynctask 都是串行执行任务的。(这就是为什么耗时任务不要在这里做的原因 你耗时了 其他资源就用不了了) 3.0以前是并行执行的

      你当然可以用executeOnExecutor来并行执行任务。如果用这个方法 你可以考虑做一些耗时任务。

    13.thread和handlerthread的区别在哪?

    答:

     1 //区别主要就在run方法里,thread的run方法就是执行一个耗时任务
     2 //而hh 在内部创建了消息队列。
     3 
     4 @Override
     5     public void run() {
     6         mTid = Process.myTid();
     7         Looper.prepare();
     8         synchronized (this) {
     9             mLooper = Looper.myLooper();
    10             notifyAll();
    11         }
    12         Process.setThreadPriority(mPriority);
    13         onLooperPrepared();
    14         //这里开启消息循环 会在消息队列的next方法那边block住,所以你不用的时候 一定记得quit!
    15         Looper.loop();
    16         mTid = -1;
    17     }
    18     
    View Code

    14.intentservice的原理?

    答:

     1 //intentservice 在onCreate方法里启动了一个handlerthread
     2 //注意service的onCreate方法 只在第一次启动时候才被调用
     3 public void onCreate() {
     4         // TODO: It would be nice to have an option to hold a partial wakelock
     5         // during processing, and to have a static startService(Context, Intent)
     6         // method that would launch the service & hand off a wakelock.
     7 
     8         super.onCreate();
     9         HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    10         thread.start();
    11 
    12         mServiceLooper = thread.getLooper();
    13         mServiceHandler = new ServiceHandler(mServiceLooper);
    14     }
    15 
    16 
    17 
    18 //而service的onStartCommand 是每次启动都被调用的
    19     public int onStartCommand(Intent intent, int flags, int startId) {
    20         onStart(intent, startId);
    21         return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    22     }
    23 
    24 //所以你看startservice 发送的intent 被传送到了这里
    25      @Override
    26     public void onStart(Intent intent, int startId) {
    27         Message msg = mServiceHandler.obtainMessage();
    28         msg.arg1 = startId;
    29         msg.obj = intent;
    30         mServiceHandler.sendMessage(msg);
    31     }
    32 
    33 //intent发送到这里被处理
    34      private final class ServiceHandler extends Handler {
    35         public ServiceHandler(Looper looper) {
    36             super(looper);
    37         }
    38 
    39         @Override
    40         public void handleMessage(Message msg) {
    41             //处理完我们的intent 就结束了 所以这个intentservice 也是顺序执行任务的
    42             onHandleIntent((Intent)msg.obj);
    43             //stopself方法是立即停止 而我们这是是用的stopself(int startId) 这个方法会等待所有消息处理完毕以后才停止
    44             stopSelf(msg.arg1);
    45         }
    46     }
    47 
    48 //这个方法教给子类去实现的。
    49      @WorkerThread
    50     protected abstract void onHandleIntent(Intent intent);
    View Code

    15.在android中使用线程池 有什么需要注意的地方?

    答:其实android中的线程池 跟java中的一模一样。就是通过Executor接口来操作的。

     1 package com.example;
     2 
     3 /**
     4  * Created by Administrator on 2016/2/15.
     5  */
     6 
     7 import java.util.concurrent.BlockingQueue;
     8 import java.util.concurrent.ExecutorService;
     9 import java.util.concurrent.Executors;
    10 import java.util.concurrent.TimeUnit;
    11 
    12 /**
    13  * 理解好线程池 主要就是理解好核心线程这个概念 核心线程 的意思 就是永远不消亡,不存在超时机制,核心线程会一直存在与线程池之中 闲置状态也会一直存在。
    14  * 非核心线程 超时以后 就自动被线程池回收了
    15  * 所以根据这一点 我们就可以根据我们的业务模型 选择合适的线程池。
    16  */
    17 public class ThreadExcutorsExample {
    18 
    19     public static void main(String[] args)
    20     {
    21         //这种线程池只有核心线程,这些线程永远不会被回收的。所以这种线程池适合 需要快速响应外界请求的 场景。
    22         ExecutorService fixedThreadPool= Executors.newFixedThreadPool(4);
    23 
    24         //这种线程池 没有核心线程,全都是非核心线程,超时时间为60s 也就是说超过60s 没有任务进来处理 就自动销毁.
    25         //最大线程数就是Intger。Maxvalue 理论上就是可以开启无线个线程。
    26         //当没有任务进来的时候 这个线程池 就没有线程了。所以适合执行 大量耗时较少的场景
    27         ExecutorService cacheThreadPool=Executors.newCachedThreadPool();
    28 
    29         //核心线程数量固定 非核心线程没有限制, 定时任务什么的 可以用这个 比较合适
    30         ExecutorService scheduledThreadPool=Executors.newScheduledThreadPool(4);
    31 
    32         //就只有一个核心线程,非核心线程也没有。所以这种线程池就是顺序处理任务的
    33         ExecutorService singleThreadPool=Executors.newSingleThreadScheduledExecutor();
    34 
    35 //  他们内部都是通过ThreadPoolExecutor这个构造方法 来构造对应的线程池的。asynctask 不同版本的源码 你都可以看看 是怎么构造的。
    36 //  其实都是这个构造函数 传递了不同的参数而已。
    37 //        public ThreadPoolExecutor(int corePoolSize,
    38 //        int maximumPoolSize,
    39 //        long keepAliveTime,
    40 //        TimeUnit unit,
    41 //        BlockingQueue<Runnable> workQueue) {
    42 //        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
    43 //                Executors.defaultThreadFactory(), defaultHandler);
    44     }
    45     }
    46 }
    View Code
  • 相关阅读:
    [模板]大数加法
    HDU 1848 Fibonacci again and again
    同时安装了Python2和Python3时的pip使用
    UPC-2785 One-Way Roads(最大流建图)
    UPC-2784 Model Railroad(最小生成树)
    【ICPC 2017 Daejeon】UPC-9312 Game Map(dfs)
    【ICPC 2015 Shenyang】UVALive
    【ICPC 2015 Shenyang 】UPC-9254 MEETING(最短路&虚点建图)
    UPC-9264 Chip Factory(01字典树)
    【ICPC 2018 Malaysia】UPC-9302 ELI'S CURIOUS MIND(递推)
  • 原文地址:https://www.cnblogs.com/punkisnotdead/p/5190912.html
Copyright © 2011-2022 走看看