上课不是很懂 在csdn、知乎上查了下进程线程协程等相关概念
进程 = 火车 线程 = 车厢
线程在进程下行进(单纯的车厢无法运行)
一个进程可以包含多个线程(一辆火车可以有多个车厢)
不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)
进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)
进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)
进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)
进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-"互斥锁"
进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”
作者:biaodianfu
链接:https://www.zhihu.com/question/25532384/answer/411179772
来源:知乎
假设你经营着一家物业管理公司。最初,业务量很小,事事都需要你亲力亲为。给老张家修完暖气管道,立马再去老李家换电灯泡——这叫单线程,所有的工作都得顺序执行。
后来业务拓展了,你雇佣了几个工人,这样,你的物业公司就可以同时为多户人家提供服务了——这叫多线程,你是主线程。
工人们使用的工具,是物业管理公司提供的,这些工具由大家共享,并不专属于某一个人——这叫多线程资源共享。
工人们在工作中都需要管钳,可是管钳只有一把——这叫冲突。解决冲突的办法有很多,比如排队等候、等同事用完后的微信通知等——这叫线程同步。
你给工人布置任务——这叫创建线程。之后你还得要告诉他,可以开始了,不然他会一直停在那儿不动——这叫启动线程(start)。
如果某个工人(线程)的工作非常重要,你(主线程)也许会亲自监工一段时间,如果不指定时间,则表示你会一直监工到该项工作完成——这叫线程参与(join)。
业务不忙的时候,你就在办公室喝喝茶。下班时间一到,你群发微信,所有的工人不管手头的工作是否完成,都立马撂下工具,跟你走人。因此如果有必要,你得避免不要在工人正忙着的时候发下班的通知——这叫线程守护属性设置和管理(daemon)。
再后来,你的公司规模扩大了,同时为很多生活社区服务,你在每个生活社区设置了分公司,分公司由分公司经理管理,运营机制和你的总公司几乎一模一样——这叫多进程,总公司叫主进程,分公司叫子进程。
总公司和分公司,以及各个分公司之间,工具都是独立的,不能借用、混用——这叫进程间不能共享资源。各个分公司之间可以通过专线电话联系——这叫管道。各个分公司之间还可以通过公司公告栏交换信息——这叫进程间共享内存。另外,各个分公司之间还有各种协同手段,以便完成更大规模的作业——这叫进程间同步。分公司可以跟着总公司一起下班,也可以把当天的工作全部做完之后再下班——这叫守护进程设置。
作者:人民邮电出版社
链接:https://www.zhihu.com/question/25532384/answer/1598653960
来源:知乎
计算机就像一个洗车场,进程就像一辆辆汽车,大的汽车占两个车位,小汽车占一个(就好比计算机会给大的程序分配更多内存)。而线程就像洗车工,每个进程至少有一个线程(有的汽车除了洗车还要检修、美容等,就需要多几个洗车工人,多几个线程)。每个线程共享该进程分配到的资源(每个洗车工人共享一定数量的洗洁精、抹布等洗车用具)
时间片即CPU分配给各个程序的时间,每个线程被分配一个时间段,称作它的时间片,即该进程允许运行的时间,使各个程序从表面上看是同时进行的。如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。而不会造成CPU资源浪费。在宏观上:我们可以同时打开多个应用程序,每个程序并行不悖,同时运行。但在微观上:由于只有一个CPU,一次只能处理程序要求的一部分,如何处理公平,一种方法就是引入时间片,每个程序轮流执行。
什么是协程?
协程其实就是一套Kotlin官方提供的线程API。就像Java的Executor和Android的AsyncTask,Kotlin的协程也对Thread相关的API做了一套封装。协程的实质:线程框架
协程的好处:方便。但由于它借助了Kotlin的语言优势,所以会比那些基于Java的方案方便一些。最重要的是,它可以用看起来同步的方式写出异步代码,这就是Kotlin最有名的【非阻塞式挂起】
集合里的filter函数
泛型:当函数可以匹配多种类型(参数类型等),但又不知道具体是什么类型,就用一个字母来表示。这个字母通常是大写,通常是T。eg:Array的拓展函数,使用泛型,那么不管是任何类型的Array都可以调用该拓展函数。
既然是泛型函数,那在函数名之前要先告诉编译器,我要用泛型X(X指任意大写字母,不是指字母X,可以是R、T、Z等)。
在调用泛型函数时,系统会根据你传的参数类型来推测此时泛型应该具体是什么类型,比如Array.findElement这个函数,当你传参数“Jack”时,系统就会推测出此时的泛型T应该指的是String。(当然也不一定只是依据参数类型,在这个例子里更多的是因为调用findElement函数的数组里存放的是String,所以系统才做出推测)