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 }