例子一:
GlobalScope.launch(Dispatchers.Main) { //開啟子協程 withContext(Dispatchers.IO) { for (i in 0 until 1000) { } Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name) } Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name) } Log.d("MainActivityXX", "onCreate-> thread:" + Thread.currentThread().name)
列印log:
2022-10-09 20:24:21.100 8371-8371/com.example.xiecheng D/MainActivityXX: onCreate-> thread:main
2022-10-09 20:24:21.131 8371-8412/com.example.xiecheng D/MainActivityXX: withContext-> thread:DefaultDispatcher-worker-1
2022-10-09 20:24:21.258 8371-8371/com.example.xiecheng D/MainActivityXX: GlobalScope-> thread:main
例子二:
GlobalScope.launch(Dispatchers.Main) { //開啟子協程 withContext(Dispatchers.IO) { for (i in 0 until 1000) { } Log.d("MainActivityXX", "withContext1-> thread:" + Thread.currentThread().name) withContext(Dispatchers.IO) { for (i in 0 until 1000) { } Log.d("MainActivityXX", "withContext2-> thread:" + Thread.currentThread().name) } } withContext(Dispatchers.IO) { for (i in 0 until 1000) { } Log.d("MainActivityXX", "withContext3-> thread:" + Thread.currentThread().name) } Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name) } Log.d("MainActivityXX", "onCreate-> thread:" + Thread.currentThread().name)
列印log:
onCreate-> thread:main withContext1-> thread:DefaultDispatcher-worker-1 withContext2-> thread:DefaultDispatcher-worker-1 withContext3-> thread:DefaultDispatcher-worker-1 GlobalScope-> thread:main
主執行緒開啟一個協程,并不會阻礙主執行緒的執行,單個協程內部是串行執行的,這里整一個都是串行執行的是因為withContext是一個掛起函式,
GlobalScope.launch(Dispatchers.Main) { //開啟子協程 GlobalScope.launch (Dispatchers.IO) { Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name) } Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name) }
列印log:
GlobalScope-> thread:main
withContext-> thread:DefaultDispatcher-worker-1
例子二:
GlobalScope.launch(Dispatchers.Main) { //開啟子協程 withContext(Dispatchers.IO) { get() Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name) } Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name) }
suspend fun get() {
Thread {
Thread.sleep(5000)
Log.d("MainActivityXX", "get-> thread:" + Thread.currentThread().name)
}.start()
}
列印log:
2022-11-01 20:56:25.220 20058-20100/com.example.xiecheng D/MainActivityXX: withContext-> thread:DefaultDispatcher-worker-1
2022-11-01 20:56:25.264 20058-20058/com.example.xiecheng D/MainActivityXX: GlobalScope-> thread:main
2022-11-01 20:56:30.222 20058-20103/com.example.xiecheng D/MainActivityXX: get-> thread:Thread-8
協程里面開啟執行緒,那么執行緒不會受協程影響,
例子三:
GlobalScope.launch(Dispatchers.Main) { fetchDocs() } suspend fun fetchDocs() { // Dispatchers.Main val result = get("https://developer.android.com") // Dispatchers.IO for `get` Log.d("MainActivityXX", "fetchDocs-> thread:" + Thread.currentThread().name) } //withContext本身就是掛起函式 suspend fun get(url: String) = withContext (Dispatchers.IO) { Log.d("MainActivityXX", "get-> thread:" + Thread.currentThread().name) }
列印log:
get-> thread:DefaultDispatcher-worker-1
fetchDocs-> thread:main
使用了掛起函式,會先等待get方法執行完再執行下面得操作,
1、掛起函式并不會阻塞其所在執行緒,這樣就極大地提高了執行緒的并發靈活度,最大化了執行緒的利用效率,
當在 ThreadA 上運行的 CoroutineA 呼叫了delay(1000L)函式指定延遲一秒后再運行,ThreadA 會轉而去執行 CoroutineB,等到一秒后再來繼續執行 CoroutineA
2、withContext本身就是掛起函式,
3、掛起的物件是協程,
4、這個 suspend 關鍵字,既然它并不是真正實作掛起,它其實是一個提醒,函式的創建者對函式的使用者的提醒:我是一個耗時函式,我被我的創建者用掛起的方式放在后臺運行,所以請在協程里呼叫我,
為什么 suspend 關鍵字并沒有實際去操作掛起,但 Kotlin 卻把它提供出來?
因為它本來就不是用來操作掛起的,掛起的操作 —— 也就是切執行緒,依賴的是掛起函式里面的實際代碼,而不是這個關鍵字,
所以這個關鍵字,只是一個提醒,
所以,創建一個 suspend 函式,為了讓它包含真正掛起的邏輯,要在它內部直接或間接呼叫 Kotlin 自帶的 suspend 函式,你的這個 suspend 才是有意義的,
5、所以這個 suspend,其實并不是起到把任何把協程掛起,或者說切換執行緒的作用,真正掛起協程這件事,是 Kotlin 的協程框架幫我們做的,
所以我們想要自己寫一個掛起函式,僅僅只加上 suspend 關鍵字是不行的,還需要函式內部直接或間接地呼叫到 Kotlin 協程框架自帶的 suspend 函式才行,
6、開發者需要明白,協程是運行于執行緒上的,一個執行緒可以運行多個(可以是幾千上萬個)協程,執行緒的調度行為是由 OS 來操縱的,而協程的調度行為是可以由開發者來指定并由編譯器來實作的,當協程 A 呼叫 delay(1000L) 函式來指定延遲1秒后再運行時,協程 A 所在的執行緒只是會轉而去執行協程 B,等到1秒后再把協程 A 加入到可調度佇列里,所以說,執行緒并不會因為協程的延時而阻塞,這樣可以極大地提高執行緒的并發靈活度,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/526065.html
標籤:Android
上一篇:將資料從一個表拆分到另一個表
