之前对kotlin协程有个比较粗糙的理解,今天便重新整理下协程相关的内容! 俗话说读书百遍,其义自见,随着使用以及对kotlin框架更有了更多的了解
kotlin的顶层是Any 那么Any和Object的不同点在于什么?
我们先看看java.lang.object类 出自于java-1_8
1.getClass 2.hashCode 3.equals 4.clone 5.tostring 6.notify 7.notifyAll 8.wait 9.finalize
kotlin Any 出自于kotlin1.6.21
1.equals 2.hashCode 3.toString
那么Any 和object 的差距 相当于Any 更加的抽象 ,方法更少嘛 !也就更抽象!
那么方法更少,少在了线程的操作以及运行时反射 和clone方法
那么相对于协程而言 号称是轻量级的线程 那么这里 我们就仅仅对线程而言 谈论少了的notify notifyall wait
在java中 notify 以及notifyall wait 是在锁机制中用于多线程竞争锁使用! 对于这三个我也不做任何说明了! 那么这里只需要说一句的就是java中会造成线程阻塞!
But 协程不会, 协程没有阻塞的概念! 只有挂起的概念.这大概就是为什么kotlin会把 Any类中的阻塞方法(类似java中 notify wait)删除把!
如果不做删除 ,那么也就没有Any什么事 也就直接用java的object 也没啥不一样把!
那么说到这里,就得来看kotlin的协程了,何谓挂起?为何没有阻塞?
阻塞的代价?
我们知道一个线程一旦调用sleep/wait后,那么当前线程就会进入阻塞状态!
假设A 线程正在工作,突然我下达指令,睡觉把! 那么这个线程就会停下来休眠,并不会继续运行后面的代码 这样的代价就是浪费资源.
关于线程阻塞浪费资源 这就不做过多介绍.
kt中没有阻塞,是不是就没有了资源浪费呢?答案是的! 在kotlin协程中的就是挂起函数
挂起的含义:
挂起的意思就是假设A线程正在做某个任务了,突然接到命令,挂起.这时线程同样不会运行后面的代码,(后面是指挂起点之后) 这时线程不是进入休眠,而是**运行别的代码去了.**等到挂起点要么被提前join要么挂起结束! 注意挂起结束并不意味着能立马运行挂起点之后的代码
从上面代码 不难发现协程好像还真的有点像线程的味道 没错 协程的整个思想就好比是一个伪线程
准确的来说是基于线程之上应用层的一套"伪线程"框架. 底层依然是线程来实现!
那么就是kotlin层的一套框架 ,不同于线程是底层的一套东西
说到这里协程到底是什么,应该已经不言而喻了!
协程是一个如果优化线程调度的框架
协程中一个线程可以执行N多个协程
这好比Android中的handlerThread
我通过handler可以不断派发任务(协程) 到UI线程去执行!
不同的是HnadlerThread 只是一个任务派发器 我把任务发过去就完事了! 而协程类似线程一样的可以控制任务的进度!
协程是一个应用层的类似线程操作的框架
协程的轻量级 这三个字代表的是协程的切换 没有什么高额的开销 ,基于单线程下 多协程的切换 是在代码层 而不是在native 层 更不会涉及到内存的切换等
到这里你基本知道协程和线程的重要区别 就是在于线程会有很大的开销 而协程没有. 线程会阻塞,而协程不会阻塞!
下面我们将对比线程和协程的区别?或许到最后你会发现 协程和线程在概念上根本就是两个东西! 或许线程就像一辆车 而协程就像开车的人罢了!
协程和线程的区别(不同点)
- 协程不会阻塞 线程会
对于单线程 线程做不同的任务 只能先做完A 再做B 中途你可以休息 但是后面的任务依然被延迟 协程可以做到像线程一样 做一半A 再做B 再做A(基于单线程) 那么挂起一半后面的A 并不代表B任务被推迟 而是可能立马运行A 如果协程A,B都被挂起 并不代表线程被阻塞 而是线程现在没事可干 ! 对于
2.协程并不会真正的去并发
并发的只是线程 协程的并发是伪装的 本质还是线程
3.线程切换 需要操作内存 协程的切换操作的任务
相同点
都是基于线程去运行的 线程是本质
总结一点就是线程调动的是系统资源 协程操作的是线程
再补充一点 不要乱用协程 , 协程虽然对资源的利用很高 但是很高代表着的就是忙碌@
特别是安卓中 如果一味的在主线程中去调用协程 不注重对协程中线程的控制 很可能会造成线程的资源紧张和忙碌 更会导致安卓UI对驱动事件响应过长 甚至引起卡顿 以及崩溃
后面将依然从源码的角度去看协程 看看协程是怎么站在伟人(线程)之上去调度线程高效运作的把
|