美文网首页
Kotlin - 协程中的那些关键点

Kotlin - 协程中的那些关键点

作者: jiagf | 来源:发表于2020-07-09 14:33 被阅读0次

### 写在前面

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还会提示:

![](https://user-gold-cdn.xitu.io/2020/5/23/17241c5bab975416?w=674&h=123&f=png&s=12837)

提示这里要移除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.真香

感谢阅读。

相关文章

网友评论

      本文标题:Kotlin - 协程中的那些关键点

      本文链接:https://www.haomeiwen.com/subject/eitscktx.html