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 }
在源码里 就限定了 你这个子线程是不能访问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 }
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 即可。
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 }
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 }
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 }
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 }
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
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);
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 }