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

 

posted @ 2016-02-15 17:10  希尔瓦娜斯女神  阅读(1250)  评论(0编辑  收藏  举报