1. 程式人生 > >Runnable( )並不一定新開執行緒

Runnable( )並不一定新開執行緒

轉自:https://blog.csdn.net/ricefcc/article/details/41912113

參考:

http://www.cnblogs.com/xirihanlin/archive/2011/04/11/2012746.html //Android中的Handler,Looper,MessageQueue和thread

https://blog.csdn.net/liumeng123321/article/details/41346361 //關於handler.post(Runnable runnable)

https://blog.csdn.net/ly502541243/article/details/52062179

 //從Handler.post(Runnable r)再一次梳理Android的訊息機制(以及handler的記憶體洩露)

 

前面談到過Threads與Runnable的區別(https://blog.csdn.net/fchyang/article/details/81941123),

這裡再補充一個特殊的區別:

extends Thread一定新開一個執行緒,但Runnable不一定新開執行緒(所謂新開執行緒,指非UI執行緒):

① 如果是implements Runnable,像extends Thread一樣,是新開了執行緒。

②如果是匿名Runnable物件new Runnable() {...},是把Runnable物件以Message形式post到UI執行緒的Looper裡執行。

 

1) Runnable 並不一定是新開一個執行緒,比如下面的呼叫方法就是執行在UI主執行緒中的:

Handler mHandler=new Handler();
mHandler.post(new Runnable(){
	@Override
	public void run() {
		// TODO Auto-generated method stub
	}
});

官方對這個方法的解釋如下,注意其中的:“The runnable will be run on the user interface thread. ”

我們可以通過呼叫handler的post方法,把Runnable物件(一般是Runnable的子類)傳過去;handler會在looper中呼叫這個Runnable的Run方法執行。

 mHandler.post(new Runnable(){......}) 好像是new 了一個 interface, 其實是new的一個實現Runnable的匿名內部類(Inner Anonymous Class),這是很簡練的寫法!

上面的程式碼可以看成是: new anonymousClass() implement Runnable{......}

Runnable是一個介面,不是一個執行緒,一般要開執行緒的類會implements Runnable。

所以:

如果我們使用匿名內部類,則是執行在UI主執行緒的;

如果我們使用implements這個Runnable介面的執行緒類,則是執行在另一個新執行緒的

 

2) View也可以post一個Runnable物件到UI執行緒你去執行:

View.post(Runnable)

boolean android.view.View.post(Runnable action)

Causes the Runnable to be added to the message queue. The runnable will be run on the user interface thread.

Parameters: 
action The Runnable that will be executed. 
Returns: 
Returns true if the Runnable was successfully placed in to the message queue. Returns false on failure, usually because the looper processing the message queue is exiting.

 

具體來說,View.post(Runnable)這個函式的工作原理如下:

在post(Runnable action)方法裡,View獲得當前執行緒(即UI執行緒)的Handler,然後將action物件post到Handler裡。在Handler裡,它將傳遞過來的action物件包裝成一個Message(Message的callback為action,即通過Message可以回撥action),然後將其投入UI執行緒的訊息迴圈中。在Handler再次處理該Message時,有一條分支(未解釋的那條)就是為它所設,直接呼叫runnable的run方法。而此時,已經路由到UI執行緒裡,因此,我們可以在這個Runnable action裡毫無顧慮的來更新UI,比如呼叫findViewById或者TextView.setText等。

如下圖,前面看到的程式碼,我們這裡Message的callback為一個Runnable的匿名內部類

這種情況下,由於不是在新的執行緒中使用,而是在UI執行緒,所以千萬別做複雜的計算邏輯。

image

參考資料:

Android中的Handler, Looper, MessageQueue和Thread 
http://www.cnblogs.com/xirihanlin/archive/2011/04/11/2012746.html

Android系列之Message機制的靈活應用 
http://tech.ddvip.com/2010-07/1280393505158258_3.html