go語(yǔ)言之行--golang核武器goroutine調(diào)度原理、channel詳解

轉(zhuǎn)載自

一嗓化、goroutine簡(jiǎn)介

goroutine是go語(yǔ)言中最為NB的設(shè)計(jì)棠涮,也是其魅力所在,goroutine的本質(zhì)是協(xié)程刺覆,是實(shí)現(xiàn)并行計(jì)算的核心严肪。goroutine使用方式非常的簡(jiǎn)單,只需使用go關(guān)鍵字即可啟動(dòng)一個(gè)協(xié)程谦屑,并且它是處于異步方式運(yùn)行驳糯,你不需要等它運(yùn)行完成以后在執(zhí)行以后的代碼。

go?func()//通過(guò)go關(guān)鍵字啟動(dòng)一個(gè)協(xié)程來(lái)運(yùn)行函數(shù)

二氢橙、goroutine內(nèi)部原理

概念介紹

在進(jìn)行實(shí)現(xiàn)原理之前酝枢,了解下一些關(guān)鍵性術(shù)語(yǔ)的概念。

并發(fā)

一個(gè)cpu上能同時(shí)執(zhí)行多項(xiàng)任務(wù)悍手,在很短時(shí)間內(nèi)隧枫,cpu來(lái)回切換任務(wù)執(zhí)行(在某段很短時(shí)間內(nèi)執(zhí)行程序a,然后又迅速得切換到程序b去執(zhí)行)谓苟,有時(shí)間上的重疊(宏觀上是同時(shí)的官脓,微觀仍是順序執(zhí)行),這樣看起來(lái)多個(gè)任務(wù)像是同時(shí)執(zhí)行,這就是并發(fā)涝焙。

并行

當(dāng)系統(tǒng)有多個(gè)CPU時(shí),每個(gè)CPU同一時(shí)刻都運(yùn)行任務(wù)卑笨,互不搶占自己所在的CPU資源,同時(shí)進(jìn)行仑撞,稱(chēng)為并行赤兴。

進(jìn)程

cpu在切換程序的時(shí)候妖滔,如果不保存上一個(gè)程序的狀態(tài)(也就是我們常說(shuō)的context--上下文),直接切換下一個(gè)程序桶良,就會(huì)丟失上一個(gè)程序的一系列狀態(tài)座舍,于是引入了進(jìn)程這個(gè)概念,用以劃分好程序運(yùn)行時(shí)所需要的資源陨帆。因此進(jìn)程就是一個(gè)程序運(yùn)行時(shí)候的所需要的基本資源單位(也可以說(shuō)是程序運(yùn)行的一個(gè)實(shí)體)曲秉。

線(xiàn)程

cpu切換多個(gè)進(jìn)程的時(shí)候,會(huì)花費(fèi)不少的時(shí)間疲牵,因?yàn)榍袚Q進(jìn)程需要切換到內(nèi)核態(tài)承二,而每次調(diào)度需要內(nèi)核態(tài)都需要讀取用戶(hù)態(tài)的數(shù)據(jù),進(jìn)程一旦多起來(lái)纲爸,cpu調(diào)度會(huì)消耗一大堆資源亥鸠,因此引入了線(xiàn)程的概念,線(xiàn)程本身幾乎不占有資源识啦,他們共享進(jìn)程里的資源负蚊,內(nèi)核調(diào)度起來(lái)不會(huì)那么像進(jìn)程切換那么耗費(fèi)資源。

協(xié)程

協(xié)程擁有自己的寄存器上下文和棧颓哮。協(xié)程調(diào)度切換時(shí)家妆,將寄存器上下文和棧保存到其他地方,在切回來(lái)的時(shí)候题翻,恢復(fù)先前保存的寄存器上下文和棧揩徊。因此腰鬼,協(xié)程能保留上一次調(diào)用時(shí)的狀態(tài)(即所有局部狀態(tài)的一個(gè)特定組合)嵌赠,每次過(guò)程重入時(shí),就相當(dāng)于進(jìn)入上一次調(diào)用的狀態(tài)熄赡,換種說(shuō)法:進(jìn)入上一次離開(kāi)時(shí)所處邏輯流的位置姜挺。線(xiàn)程和進(jìn)程的操作是由程序觸發(fā)系統(tǒng)接口,最后的執(zhí)行者是系統(tǒng)彼硫;協(xié)程的操作執(zhí)行者則是用戶(hù)自身程序炊豪,goroutine也是協(xié)程。


調(diào)度模型簡(jiǎn)介

groutine能擁有強(qiáng)大的并發(fā)實(shí)現(xiàn)是通過(guò)GPM調(diào)度模型實(shí)現(xiàn)拧篮,下面就來(lái)解釋下goroutine的調(diào)度模型词渤。

Go的調(diào)度器內(nèi)部有四個(gè)重要的結(jié)構(gòu):M,P串绩,S缺虐,Sched,如上圖所示(Sched未給出)

M:M代表內(nèi)核級(jí)線(xiàn)程礁凡,一個(gè)M就是一個(gè)線(xiàn)程高氮,goroutine就是跑在M之上的慧妄;M是一個(gè)很大的結(jié)構(gòu),里面維護(hù)小對(duì)象內(nèi)存cache(mcache)剪芍、當(dāng)前執(zhí)行的goroutine塞淹、隨機(jī)數(shù)發(fā)生器等等非常多的信息

G:代表一個(gè)goroutine,它有自己的棧罪裹,instruction pointer和其他信息(正在等待的channel等等)饱普,用于調(diào)度。

P:P全稱(chēng)是Processor坊谁,處理器费彼,它的主要用途就是用來(lái)執(zhí)行g(shù)oroutine的,所以它也維護(hù)了一個(gè)goroutine隊(duì)列口芍,里面存儲(chǔ)了所有需要它來(lái)執(zhí)行的goroutine

Sched:代表調(diào)度器箍铲,它維護(hù)有存儲(chǔ)M和G的隊(duì)列以及調(diào)度器的一些狀態(tài)信息等。


調(diào)度實(shí)現(xiàn)

從上圖中看鬓椭,有2個(gè)物理線(xiàn)程M颠猴,每一個(gè)M都擁有一個(gè)處理器P,每一個(gè)也都有一個(gè)正在運(yùn)行的goroutine小染。

P的數(shù)量可以通過(guò)GOMAXPROCS()來(lái)設(shè)置翘瓮,它其實(shí)也就代表了真正的并發(fā)度,即有多少個(gè)goroutine可以同時(shí)運(yùn)行裤翩。

圖中灰色的那些goroutine并沒(méi)有運(yùn)行资盅,而是出于ready的就緒態(tài),正在等待被調(diào)度踊赠。P維護(hù)著這個(gè)隊(duì)列(稱(chēng)之為runqueue)呵扛,

Go語(yǔ)言里,啟動(dòng)一個(gè)goroutine很容易:go function 就行筐带,所以每有一個(gè)go語(yǔ)句被執(zhí)行今穿,runqueue隊(duì)列就在其末尾加入一個(gè)

goroutine,在下一個(gè)調(diào)度點(diǎn)伦籍,就從runqueue中取出(如何決定取哪個(gè)goroutine蓝晒?)一個(gè)goroutine執(zhí)行。


當(dāng)一個(gè)OS線(xiàn)程M0陷入阻塞時(shí)(如下圖)帖鸦,P轉(zhuǎn)而在運(yùn)行M1芝薇,圖中的M1可能是正被創(chuàng)建,或者從線(xiàn)程緩存中取出作儿。


當(dāng)MO返回時(shí)洛二,它必須嘗試取得一個(gè)P來(lái)運(yùn)行g(shù)oroutine,一般情況下,它會(huì)從其他的OS線(xiàn)程那里拿一個(gè)P過(guò)來(lái)灭红,

如果沒(méi)有拿到的話(huà)侣滩,它就把goroutine放在一個(gè)global runqueue里,然后自己睡眠(放入線(xiàn)程緩存里)变擒。所有的P也會(huì)周期性的檢查global runqueue并運(yùn)行其中的goroutine君珠,否則global runqueue上的goroutine永遠(yuǎn)無(wú)法執(zhí)行。


另一種情況是P所分配的任務(wù)G很快就執(zhí)行完了(分配不均)娇斑,這就導(dǎo)致了這個(gè)處理器P很忙策添,但是其他的P還有任務(wù),此時(shí)如果global runqueue沒(méi)有任務(wù)G了毫缆,那么P不得不從其他的P里拿一些G來(lái)執(zhí)行唯竹。一般來(lái)說(shuō),如果P從其他的P那里要拿任務(wù)的話(huà)苦丁,一般就拿run queue的一半浸颓,這就確保了每個(gè)OS線(xiàn)程都能充分的使用,如下圖:

參考地址:http://morsmachine.dk/go-scheduler



三旺拉、使用goroutine

基本使用

設(shè)置goroutine運(yùn)行的CPU數(shù)量产上,最新版本的go已經(jīng)默認(rèn)已經(jīng)設(shè)置了。

num?:=?runtime.NumCPU()????//獲取主機(jī)的邏輯CPU個(gè)數(shù)runtime.GOMAXPROCS(num)????//設(shè)置可同時(shí)執(zhí)行的最大CPU數(shù)

使用示例

package?main

import?(????"fmt"

????"time")

func?cal(a?int?,?b?int?)??{

????c?:=?a+b

????fmt.Printf("%d?+?%d?=?%d\n",a,b,c)

}

func?main()?{

  ????for?i?:=0?;?i<10?;i++{

????????go?cal(i,i+1)??//啟動(dòng)10個(gè)goroutine?來(lái)計(jì)算????}

????time.Sleep(time.Second?*?2)?//?sleep作用是為了等待所有任務(wù)完成}?

//結(jié)果//8?+?9?=?17//9?+?10?=?19//4?+?5?=?9//5?+?6?=?11//0?+?1?=?1//1?+?2?=?3//2?+?3?=?5//3?+?4?=?7//7?+?8?=?15//6?+?7?=?13

goroutine異常捕捉

當(dāng)啟動(dòng)多個(gè)goroutine時(shí)蛾狗,如果其中一個(gè)goroutine異常了晋涣,并且我們并沒(méi)有對(duì)進(jìn)行異常處理,那么整個(gè)程序都會(huì)終止沉桌,所以我們?cè)诰帉?xiě)程序時(shí)候最好每個(gè)goroutine所運(yùn)行的函數(shù)都做異常處理谢鹊,異常處理采用recover

package?main

import?(????"fmt"

????"time")

func?addele(a?[]int?,i?int)??{

????defer?func()?{????//匿名函數(shù)捕獲錯(cuò)誤

????????err?:=?recover()????????if?err?!=?nil?{

????????????fmt.Println("add?ele?fail")

????????}

????}()

???a[i]=i

???fmt.Println(a)

}

func?main()?{

????Arry?:=?make([]int,4)????for?i?:=0?;?i<10?;i++{

????????go?addele(Arry,i)

????}

????time.Sleep(time.Second?*?2)

}//結(jié)果add?ele?fail

[0?0?0?0]

[0?1?0?0]

[0?1?2?0]

[0?1?2?3]

add?ele?fail

add?ele?fail

add?ele?fail

add?ele?fail

add?ele?fail

同步的goroutine

由于goroutine是異步執(zhí)行的,那很有可能出現(xiàn)主程序退出時(shí)還有g(shù)oroutine沒(méi)有執(zhí)行完留凭,此時(shí)goroutine也會(huì)跟著退出佃扼。此時(shí)如果想等到所有g(shù)oroutine任務(wù)執(zhí)行完畢才退出,go提供了sync包和channel來(lái)解決同步問(wèn)題冰抢,當(dāng)然如果你能預(yù)測(cè)每個(gè)goroutine執(zhí)行的時(shí)間松嘶,你還可以通過(guò)time.Sleep方式等待所有的groutine執(zhí)行完成以后在退出程序(如上面的列子)艘狭。

示例一:使用sync包同步goroutine

sync大致實(shí)現(xiàn)方式

WaitGroup 等待一組goroutinue執(zhí)行完畢. 主程序調(diào)用 Add 添加等待的goroutinue數(shù)量. 每個(gè)goroutinue在執(zhí)行結(jié)束時(shí)調(diào)用 Done 挎扰,此時(shí)等待隊(duì)列數(shù)量減1.,主程序通過(guò)Wait阻塞巢音,直到等待隊(duì)列為0.


package?main

import?(????"fmt"

????"sync")

func?cal(a?int?,?b?int?,n?*sync.WaitGroup)??{

????c?:=?a+b

????fmt.Printf("%d?+?%d?=?%d\n",a,b,c)

????defer?n.Done()?//goroutinue完成后,?WaitGroup的計(jì)數(shù)-1}

func?main()?{????var?go_sync?sync.WaitGroup?//聲明一個(gè)WaitGroup變量

????for?i?:=0?;?i<10?;i++{

????????go_sync.Add(1)?//?WaitGroup的計(jì)數(shù)加1

????????go?cal(i,i+1,&go_sync)??

????}

????go_sync.Wait()??//等待所有g(shù)oroutine執(zhí)行完畢}//結(jié)果9?+?10?=?192?+?3?=?53?+?4?=?74?+?5?=?95?+?6?=?111?+?2?=?36?+?7?=?137?+?8?=?150?+?1?=?18?+?9?=?17

示例二:通過(guò)channel實(shí)現(xiàn)goroutine之間的同步遵倦。

實(shí)現(xiàn)方式:通過(guò)channel能在多個(gè)groutine之間通訊,當(dāng)一個(gè)goroutine完成時(shí)候向channel發(fā)送退出信號(hào),等所有g(shù)oroutine退出時(shí)候官撼,利用for循環(huán)channe去channel中的信號(hào)梧躺,若取不到數(shù)據(jù)會(huì)阻塞原理,等待所有g(shù)oroutine執(zhí)行完畢,使用該方法有個(gè)前提是你已經(jīng)知道了你啟動(dòng)了多少個(gè)goroutine掠哥。

package?main

import?(????"fmt"

????"time")

func?cal(a?int?,?b?int?,Exitchan?chan?bool)??{

????c?:=?a+b

????fmt.Printf("%d?+?%d?=?%d\n",a,b,c)

????time.Sleep(time.Second*2)

????Exitchan?<-?true}

func?main()?{

????Exitchan?:=?make(chan?bool,10)??//聲明并分配管道內(nèi)存

????for?i?:=0?;?i<10?;i++{

????????go?cal(i,i+1,Exitchan)

????}????for?j?:=0;?j<10;?j++{???

?????????<-?Exitchan??//取信號(hào)數(shù)據(jù)巩踏,如果取不到則會(huì)阻塞????}

????close(Exitchan)?//?關(guān)閉管道}

goroutine之間的通訊

goroutine本質(zhì)上是協(xié)程,可以理解為不受內(nèi)核調(diào)度续搀,而受go調(diào)度器管理的線(xiàn)程塞琼。goroutine之間可以通過(guò)channel進(jìn)行通信或者說(shuō)是數(shù)據(jù)共享,當(dāng)然你也可以使用全局變量來(lái)進(jìn)行數(shù)據(jù)共享禁舷。

示例:使用channel模擬消費(fèi)者和生產(chǎn)者模式

package?main

import?(????"fmt"

????"sync")

func?Productor(mychan?chan?int,data?int,wait?*sync.WaitGroup)??{

????mychan?<-?data

????fmt.Println("product?data:",data)

????wait.Done()

}

func?Consumer(mychan?chan?int,wait?*sync.WaitGroup)??{

?????a?:=?<-?mychan

????fmt.Println("consumer?data:",a)

?????wait.Done()

}

func?main()?{

????datachan?:=?make(chan?int,?100)???//通訊數(shù)據(jù)管道

????var?wg?sync.WaitGroup????for?i?:=?0;?i?<?10;?i++?{

????????go?Productor(datachan,?i,&wg)?//生產(chǎn)數(shù)據(jù)

????????wg.Add(1)

????}????for?j?:=?0;?j?<?10;?j++?{

????????go?Consumer(datachan,&wg)??//消費(fèi)數(shù)據(jù)

????????wg.Add(1)

????}

????wg.Wait()

}//結(jié)果consumer?data:?4product?data:?5product?data:?6product?data:?7product?data:?8product?data:?9consumer?data:?1consumer?data:?5consumer?data:?6consumer?data:?7consumer?data:?8consumer?data:?9product?data:?2consumer?data:?2product?data:?3consumer?data:?3product?data:?4consumer?data:?0product?data:?0product?data:?1


四彪杉、channel

簡(jiǎn)介

channel俗稱(chēng)管道,用于數(shù)據(jù)傳遞或數(shù)據(jù)共享牵咙,其本質(zhì)是一個(gè)先進(jìn)先出的隊(duì)列派近,使用goroutine+channel進(jìn)行數(shù)據(jù)通訊簡(jiǎn)單高效,同時(shí)也線(xiàn)程安全洁桌,多個(gè)goroutine可同時(shí)修改一個(gè)channel渴丸,不需要加鎖。

channel可分為三種類(lèi)型:

只讀channel:只能讀channel里面數(shù)據(jù)另凌,不可寫(xiě)入

只寫(xiě)channel:只能寫(xiě)數(shù)據(jù)曙强,不可讀

一般channel:可讀可寫(xiě)

channel使用

定義和聲明

var?readOnlyChan?<-chan?int????????????//?只讀chanvar?writeOnlyChan?chan<-?int???????????//?只寫(xiě)chanvar?mychan??chan?int?????????????????????//讀寫(xiě)channel//定義完成以后需要make來(lái)分配內(nèi)存空間,不然使用會(huì)deadlockmychannel?=?make(chan?int,10)//或者read_only?:=?make?(<-chan?int,10)//定義只讀的channelwrite_only?:=?make?(chan<-?int,10)//定義只寫(xiě)的channelread_write?:=?make?(chan?int,10)//可同時(shí)讀寫(xiě)

?讀寫(xiě)數(shù)據(jù)

需要注意的是:

管道如果未關(guān)閉途茫,在讀取超時(shí)會(huì)則會(huì)引發(fā)deadlock異常

管道如果關(guān)閉進(jìn)行寫(xiě)入數(shù)據(jù)會(huì)pannic

當(dāng)管道中沒(méi)有數(shù)據(jù)時(shí)候再行讀取或讀取到默認(rèn)值碟嘴,如int類(lèi)型默認(rèn)值是0

ch?<-?"wd"??//寫(xiě)數(shù)據(jù)a?:=?<-?ch?//讀取數(shù)據(jù)a,?ok?:=?<-ch??//優(yōu)雅的讀取數(shù)據(jù)

循環(huán)管道

需要注意的是:

使用range循環(huán)管道,如果管道未關(guān)閉會(huì)引發(fā)deadlock錯(cuò)誤囊卜。

如果采用for死循環(huán)已經(jīng)關(guān)閉的管道娜扇,當(dāng)管道沒(méi)有數(shù)據(jù)時(shí)候,讀取的數(shù)據(jù)會(huì)是管道的默認(rèn)值栅组,并且循環(huán)不會(huì)退出雀瓢。

package?main

import?(????"fmt"

????"time")

func?main()?{

????mychannel?:=?make(chan?int,10)????for?i?:=?0;i?<?10;i++{

????????mychannel?<-?i

????}

????close(mychannel)??//關(guān)閉管道

????fmt.Println("data?lenght:?",len(mychannel))????for??v?:=?range?mychannel?{??//循環(huán)管道????????fmt.Println(v)

????}

????fmt.Printf("data?lenght:??%d",len(mychannel))

}

帶緩沖區(qū)channe和不帶緩沖區(qū)channel

帶緩沖區(qū)channel:定義聲明時(shí)候制定了緩沖區(qū)大小(長(zhǎng)度),可以保存多個(gè)數(shù)據(jù)玉掸。

不帶緩沖區(qū)channel:只能存一個(gè)數(shù)據(jù)刃麸,并且只有當(dāng)該數(shù)據(jù)被取出時(shí)候才能存下一個(gè)數(shù)據(jù)。

ch?:=?make(chan?int)?//不帶緩沖區(qū)ch?:=?make(chan?int?,10)?//帶緩沖區(qū)

不帶緩沖區(qū)示例:

package?main

import?"fmt"func?test(c?chan?int)?{????for?i?:=?0;?i?<?10;?i++?{

????????fmt.Println("send?",?i)

????????c?<-?i

????}

}

func?main()?{

????ch?:=?make(chan?int)

????go?test(ch)????for?j?:=?0;?j?<?10;?j++?{

????????fmt.Println("get?",?<-ch)

????}

}//結(jié)果:send??0send??1get??0get??1send??2send??3get??2get??3send??4send??5get??4get??5send??6send??7get??6get??7send??8send??9get??8get??9

channel實(shí)現(xiàn)作業(yè)池

我們創(chuàng)建三個(gè)channel司浪,一個(gè)channel用于接受任務(wù)泊业,一個(gè)channel用于保持結(jié)果,還有個(gè)channel用于決定程序退出的時(shí)候啊易。

package?main

import?(????"fmt")

func?Task(taskch,?resch?chan?int,?exitch?chan?bool)?{

????defer?func()?{???//異常處理

????????err?:=?recover()????????if?err?!=?nil?{

????????????fmt.Println("do?task?error:",?err)????????????return

????????}

????}()????for?t?:=?range?taskch?{?//??處理任務(wù)

????????fmt.Println("do?task?:",?t)

????????resch?<-?t?//????}

????exitch?<-?true?//處理完發(fā)送退出信號(hào)}

func?main()?{

????taskch?:=?make(chan?int,?20)?//任務(wù)管道

????resch?:=?make(chan?int,?20)??//結(jié)果管道

????exitch?:=?make(chan?bool,?5)?//退出管道????go?func()?{????????for?i?:=?0;?i?<?10;?i++?{

????????????taskch?<-?i

????????}

????????close(taskch)

????}()????for?i?:=?0;?i?<?5;?i++?{??//啟動(dòng)5個(gè)goroutine做任務(wù)????????go?Task(taskch,?resch,?exitch)

????}

????go?func()?{?//等5個(gè)goroutine結(jié)束

????????for?i?:=?0;?i?<?5;?i++?{????????????<-exitch

????????}

????????close(resch)??//任務(wù)處理完成關(guān)閉結(jié)果管道吁伺,不然range報(bào)錯(cuò)

????????close(exitch)??//關(guān)閉退出管道????}()????for?res?:=?range?resch{??//打印結(jié)果

????????fmt.Println("task?res:",res)

????}

}

只讀channel和只寫(xiě)channel

一般定義只讀和只寫(xiě)的管道意義不大,更多時(shí)候我們可以在參數(shù)傳遞時(shí)候指明管道可讀還是可寫(xiě)租谈,即使當(dāng)前管道是可讀寫(xiě)的篮奄。

package?main

import?(????"fmt"

????"time")//只能向chan里寫(xiě)數(shù)據(jù)func?send(c?chan<-?int)?{????for?i?:=?0;?i?<?10;?i++?{

????????c?<-?i

????}

}//只能取channel中的數(shù)據(jù)func?get(c?<-chan?int)?{????for?i?:=?range?c?{

????????fmt.Println(i)

????}

}

func?main()?{

????c?:=?make(chan?int)

????go?send(c)

????go?get(c)

????time.Sleep(time.Second*1)

}//結(jié)果0123456789


select-case實(shí)現(xiàn)非阻塞channel

原理通過(guò)select+case加入一組管道,當(dāng)滿(mǎn)足(這里說(shuō)的滿(mǎn)足意思是有數(shù)據(jù)可讀或者可寫(xiě))select中的某個(gè)case時(shí)候,那么該case返回窟却,若都不滿(mǎn)足case昼丑,則走default分支。

package?main

import?(????"fmt")

func?send(c?chan?int)??{????for?i?:=1?;?i<10?;i++??{

?????c?<-i

?????fmt.Println("send?data?:?",i)

????}

}

func?main()?{

????resch?:=?make(chan?int,20)

????strch?:=?make(chan?string,10)

????go?send(resch)

????strch?<-?"wd"

????select?{????case?a?:=?<-resch:

????????fmt.Println("get?data?:?",?a)????case?b?:=?<-strch:

????????fmt.Println("get?data?:?",?b)????default:

????????fmt.Println("no?channel?actvie")

????}

}//結(jié)果:get?data?:??wd

channel頻率控制

在對(duì)channel進(jìn)行讀寫(xiě)的時(shí)夸赫,go還提供了非常人性化的操作矾克,那就是對(duì)讀寫(xiě)的頻率控制,通過(guò)time.Ticke實(shí)現(xiàn)

示例:

package?main

import?(????"time"

????"fmt")

func?main(){

????requests:=?make(chan?int?,5)????for?i:=1;i<5;i++{

????????requests<-i

????}

????close(requests)

????limiter?:=?time.Tick(time.Second*1)????for?req:=range?requests{????????<-limiter

????????fmt.Println("requets",req,time.Now())?//執(zhí)行到這里憔足,需要隔1秒才繼續(xù)往下執(zhí)行胁附,time.Tick(timer)上面已定義????}

}//結(jié)果:requets?1?2018-07-06?10:17:35.98056403?+0800?CST?m=+1.004248763requets?2?2018-07-06?10:17:36.978123472?+0800?CST?m=+2.001798205requets?3?2018-07-06?10:17:37.980869517?+0800?CST?m=+3.004544250requets?4?2018-07-06?10:17:38.976868836?+0800?CST?m=+4.000533569

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市滓彰,隨后出現(xiàn)的幾起案子控妻,更是在濱河造成了極大的恐慌,老刑警劉巖揭绑,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弓候,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡他匪,警方通過(guò)查閱死者的電腦和手機(jī)菇存,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)邦蜜,“玉大人依鸥,你說(shuō)我怎么就攤上這事〉可颍” “怎么了贱迟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)絮供。 經(jīng)常有香客問(wèn)我衣吠,道長(zhǎng),這世上最難降的妖魔是什么壤靶? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任缚俏,我火速辦了婚禮,結(jié)果婚禮上贮乳,老公的妹妹穿的比我還像新娘忧换。我一直安慰自己,他們只是感情好塘揣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布包雀。 她就那樣靜靜地躺著宿崭,像睡著了一般亲铡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,208評(píng)論 1 299
  • 那天奖蔓,我揣著相機(jī)與錄音赞草,去河邊找鬼。 笑死吆鹤,一個(gè)胖子當(dāng)著我的面吹牛厨疙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疑务,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼沾凄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了知允?” 一聲冷哼從身側(cè)響起撒蟀,我...
    開(kāi)封第一講書(shū)人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎温鸽,沒(méi)想到半個(gè)月后保屯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涤垫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年姑尺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝠猬。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡切蟋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出榆芦,到底是詐尸還是另有隱情敦姻,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布歧杏,位于F島的核電站镰惦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏犬绒。R本人自食惡果不足惜旺入,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凯力。 院中可真熱鬧茵瘾,春花似錦、人聲如沸咐鹤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)祈惶。三九已至雕旨,卻和暖如春扮匠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凡涩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工棒搜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人活箕。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓力麸,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親育韩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子克蚂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1989年進(jìn)這一行 , 不經(jīng)不覺(jué)快三十個(gè)年頭了 ! 真快 ! 還記得那個(gè)時(shí)候剪周星馳做的兒童節(jié)目 …… 還記得劉青...
    先死後生李傑生閱讀 326評(píng)論 0 1
  • L5 1.你認(rèn)為電商運(yùn)營(yíng)的成本包括哪些?在電子商務(wù)實(shí)際運(yùn)營(yíng)中發(fā)現(xiàn)有哪些利用價(jià)格去吸引消費(fèi)者的方法筋讨? 成本:1.網(wǎng)站...
    0bb1fb08c313閱讀 177評(píng)論 0 0
  • 想喝酒陨舱,想喝的醉醺醺,結(jié)婚后有點(diǎn)像被拋棄了版仔,以前還有我的家游盲、我的家人可以訴說(shuō),現(xiàn)在我能說(shuō)蛮粮,不敢說(shuō)益缎,怕他們擔(dān)心,怕他...
    錄望閱讀 158評(píng)論 0 0
  • 最近持續(xù)低迷的狀態(tài)終于解決了然想,我深深地明白了一個(gè)道理莺奔,如果自己沒(méi)有把握贏得勝利,那就找一個(gè)人变泄,讓她逼著你前進(jìn)令哟,畢竟...
    海豚的世界閱讀 972評(píng)論 0 0