Kotlin - 协程中的那些关键点

写在前面

1.协程“非阻塞式挂起” 你真的弄懂了吗?

2.协程suspend关键字到底有多神奇?

3.协程有了launch,还要async干啥?抱小三?

4.协程真的高大上吗?

1.非阻塞式挂起

阻塞:即程序因耗时操作等原因阻止线程继续运行

非阻塞:即不阻止程序继续运行

挂起:即wait,释放已经获取到的线程资源

非阻塞式挂起:不阻止程序运行,还释放了已经获取到的线程资源

那么问题来了,你把资源都释放了我咋继续后续操作?

Are you kid me?

他到底干了啥,有人说是关键字suspend,但是但是,你看下面代码难道执行有区别吗?

//测试代码1
GlobalScope.launch(Dispatchers.Main) {
           dealprint()
        }
        
        

//测试代码2
GlobalScope.launch(Dispatchers.Main) {
          dealTask()
}
    

    suspend fun dealTask() = withContext(Dispatchers.Default){
         Log.i(TAG,"Task:")
    }
    
    suspend fun dealprint(){
        Log.i(TAG,"print:")
    }

难道只有代码2才是非阻塞式挂起?代码1不是。

说对了,代码1不是 suspend。dealprint这里的suspend还会提示:

提示这里要移除suspend,那就可能是其他的关键点了,关键点就是切换线程

launch withContext async 等

2.suspend

suspend究竟是用来做什么呢?

suspend关键字只是一个提醒,不对两个提醒

提醒1: 我要切换线程了,下边的代码在另一个线程执行

提醒2: 我只能在协程中执行,因为执行完当前suspend方法我要切回到原先的协程继续执行后续操作

3.async

async 同步

上代码

suspend fun dealAsyncTask1(): Int {
       delay(3000)
       Log.i(TAG, "dealAsyncTask1")
       return 3
   }

   suspend fun dealAsyncTask2(): Int {
       delay(2000)
       Log.i(TAG, "dealAsyncTask2")
       return 2
   }
   
   //代码一

  GlobalScope.launch(Dispatchers.Default) {
           Log.i(TAG, "dealAsyncTask--start:")
           val one =  dealAsyncTask1()
           val two =  dealAsyncTask2()
           Log.i(TAG, "dealAsyncTask:${(one + two)}")
       }
//代码二
       GlobalScope.launch(Dispatchers.Default) {
           Log.i(TAG, "dealAsyncTask--start--async:")
           val one = async { dealAsyncTask1() }
           val two = async { dealAsyncTask2() }
           Log.i(TAG, "dealAsyncTask--async:${(one.await() + two.await())}")
       }

代码一和代码二的区别是什么,结果是一样的吗?

先上日志:

07-08 19:02:08.717 30075-30127/com.matt.mattdemo I/MainActivity: dealAsyncTask--start:
07-08 19:02:08.717 30075-30128/com.matt.mattdemo I/MainActivity: dealAsyncTask--start--async:
07-08 19:02:10.737 30075-30127/com.matt.mattdemo I/MainActivity: dealAsyncTask2
07-08 19:02:11.727 30075-30127/com.matt.mattdemo I/MainActivity: dealAsyncTask1
07-08 19:02:11.727 30075-30127/com.matt.mattdemo I/MainActivity: dealAsyncTask--async:5
07-08 19:02:11.727 30075-30127/com.matt.mattdemo I/MainActivity: dealAsyncTask1
07-08 19:02:13.737 30075-30127/com.matt.mattdemo I/MainActivity: dealAsyncTask2
07-08 19:02:13.737 30075-30127/com.matt.mattdemo I/MainActivity: dealAsyncTask:5

可以看到async执行的时间比默认执行短了2s,为啥会短,这就是async的本质,加了async会让代码块程序并发执行,dealAsyncTask2和dealAsyncTask1并发执行,而不是依次执行,好,这个方法太棒了

当然还有更多的async启动模式

public enum class CoroutineStart {
		DEFAULT,
		LAZY,
		ATOMIC,
		UNDISPATCHED
}

//DEFAULT: 默认值,它会上下文立即调度线程的执行
//LAZY:它不会立即调度协程的执行,而是在需要的时候才会触发执行
//ATOMIC:原子性调度,即不会被取消
//UNDISPATCHED:也会立即调度,直到当前的第一个挂起点,这个后面讨论分发器的时候还会说

使用方式

async(start = CoroutineStart.LAZY) { dealAsyncTask1() }

]

啊,老师,我有问题,我用了这个LAZY后还是依次执行啊,并不是你那样啊?

what??


GlobalScope.launch(Dispatchers.Default) {
            Log.i(TAG, "dealAsyncTask--start:")
            val one =  dealAsyncTask1()
            val two =  dealAsyncTask2()
            Log.i(TAG, "dealAsyncTask--normal:${(one + two)}")
        }

        GlobalScope.launch(Dispatchers.Default) {
            Log.i(TAG, "dealAsyncTask--start--async:")
            val one = async(start = CoroutineStart.LAZY) { dealAsyncTask1() }
            val two = async(start = CoroutineStart.LAZY) { dealAsyncTask2() }
            Log.i(TAG, "dealAsyncTask--async:${(one.await() + two.await())}")
        }

日志:

07-08 19:10:42.157 32265-32317/com.matt.mattdemo I/MainActivity: dealAsyncTask--start:
07-08 19:10:42.157 32265-32318/com.matt.mattdemo I/MainActivity: dealAsyncTask--start--async:
07-08 19:10:45.157 32265-32318/com.matt.mattdemo I/MainActivity: dealAsyncTask1
07-08 19:10:45.157 32265-32318/com.matt.mattdemo I/MainActivity: dealAsyncTask1
07-08 19:10:47.157 32265-32321/com.matt.mattdemo I/MainActivity: dealAsyncTask2
07-08 19:10:47.157 32265-32321/com.matt.mattdemo I/MainActivity: dealAsyncTask--normal:5
07-08 19:10:47.167 32265-32321/com.matt.mattdemo I/MainActivity: dealAsyncTask2
07-08 19:10:47.167 32265-32321/com.matt.mattdemo I/MainActivity: dealAsyncTask--async:5

呃,这里还有一个问题就是await,LAZY的是按需执行,那么就是需要时才执行了,所以只有等他调用await获取结果的时候,才会执行相应的方法,所以就是依次执行了。

嗯,终于出坑了。

4.协程真的高大上吗

真香,但是香到了什么程度呢?

1.他封装了线程池,旧概念新炒,千万别被官方比线程好多少忽悠了,线程池比线程 也好

2.调度的概念真的很棒,包括语法也很棒,比rxJava的可读可用强太多了

3.效率真的没有显著提升

4.真正的效率Only使用

5.真香

感谢阅读。

### 关于 UniApp 框架推荐资源与教程 #### 1. **Uniapp 官方文档** 官方文档是最权威的学习资料之一,涵盖了从基础概念到高级特性的全方位讲解。对于初学者来说,这是了解 UniApp 架构技术细节的最佳起点[^3]。 #### 2. **《Uniapp 从入门到精通:案例分析与最佳实践》** 该文章提供了系统的知识体系,帮助开发者掌握 Uniapp 的基础知识、实际应用以及开发过程中的最佳实践方法。它不仅适合新手快速上手,也能够为有经验的开发者提供深入的技术指导[^1]。 #### 3. **ThorUI-uniapp 开源项目教程** 这是一个专注于 UI 组件库设计实现的教学材料,基于 ThorUI 提供了一系列实用的功能模块。通过学习此开源项目的具体实现方式,可以更好地理解如何高效构建美观且一致的应用界面[^2]。 #### 4. **跨平台开发利器:UniApp 全面解析与实践指南** 这篇文章按照章节形式详细阐述了 UniApp 的各个方面,包括但不限于其工作原理、技术栈介绍、开发环境配置等内容,并附带丰富的实例演示来辅助说明理论知识点。 以下是几个重要的主题摘选: - **核心特性解析**:解释了跨端运行机制、底层架构组成及其主要功能特点。 - **开发实践指南**:给出了具体的页面编写样例代码,展示了不同设备间 API 调用的方法论。 - **性能优化建议**:针对启动时间缩短、图形绘制效率提升等方面提出了可行策略。 ```javascript // 示例代码片段展示条件编译语法 export default { methods: { showPlatform() { console.log(process.env.UNI_PLATFORM); // 输出当前平台名称 #ifdef APP-PLUS console.log('Running on App'); #endif #ifdef H5 console.log('Running on Web'); #endif } } } ``` #### 5. **其他补充资源** 除了上述提到的内容外,还有许多在线课程视频可供选择,比如 Bilibili 上的一些免费系列讲座;另外 GitHub GitCode 平台上也有不少优质的社区贡献作品值得借鉴研究。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值