中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go(8[Goroutine | Channel | 讀寫鎖 | 異常處理 ])

發布時間:2020-07-11 06:46:12 來源:網絡 閱讀:4341 作者:zhaichaoqun 欄目:編程語言

進程和線程

1. 進程是程序在操作系統中的?次執?過程,系統進口資源分配和調度的一個獨力單位。

2. 線程是進程的一個執行實體,是CPU調度和分派的基本單位,它是?進程更?的能獨力運行的基本單位。

3. 一個進程可以創建和撤銷多個線程;同一個進程中的多個線程之間可以并發執行

Goroutine


Go(8[Goroutine | Channel  | 讀寫鎖 | 異常處理 ])

并發和并行

  • 多線程程序在一個核的CPU上運行,就是并發

  • 多線程程序在多個核的CPU上運行,就是并發

設置GO運行的CPU核數

func Test1()  {
    num := runtime.NumCPU()
    //設置程序運行占幾個核
    runtime.GOMAXPROCS(num)
    fmt.Println(num)
}

線程同步

sync.WaitGroup

package main

import (
	"fmt"
	"time"
	"sync"
)

var wailtGroup  sync.WaitGroup
//sync 線程同步
func Test2(index int)  {
	for i:=0;i<100;i++{
		time.Sleep(time.Millisecond)
	}
	wailtGroup.Done()
}
func calc()  {
	start :=time.Now().UnixNano()
	//Test2(0)
	for i:=0; i<3;i++{
		go Test2(i)
		wailtGroup.Add(1)
	}
        #當wailtGroup 為0時,就會返回
	wailtGroup.Wait()
	end := time.Now().UnixNano()

	fmt.Printf("finished,cost:%d ms \n",(end - start) / 1000 / 1000)
}

func main()  {
	//Test1()
	calc()
}


不同goroutine之間通信

  1. 全局變量和鎖同步

  2. Channel


Channel

  1. 類似unix中的管道(pipe)

  2. 先進先出

  3. 線程安全,多個goroutine同時訪問,不需要加鎖

  4. Channel是有類型的,一個整數的channel只能存放整數

Channel聲明:

    var 變量名 chan 類型

                var test chan int

    var test chan string

    var test chan map[string]string

    var test chan stu

    var test chan *stu

Channel初始化:

  1. 不帶緩沖區:默認就是0,必須有取值,才可以放入,不然就會阻塞!

  2. 帶緩沖區: 值>0

            使用make進行初始化

            var test chan int

            test =make(chan int,10) 

             var test2 chan string

            test = make(chan string,10)

 Channel基本操作:

1.從channel讀取數據

testChan :=make(chan int,10)
var a int
a = <- testChan

2.從channel寫數據

testChan:=make(chan int,10)
var a int=  10
testChan <- a

栗子:

1.初級操作

func test()  {
    var intChan chan int = make(chan  int,3)
    go func(){
        fmt.Println("begin input to chan\n")
        intChan <- 20
        intChan <- 20
        intChan <- 20
        fmt.Println("end input to chan\n")
    }()
    result := <- intChan
    fmt.Printf("--result:%d",result)
    time.Sleep(2*time.Second)
}
func main()  {
    test()
}

2.goroutine和channel結合

package main
import (
"fmt"
"time"
)
func main() {
    ch := make(chan string)
    go sendData(ch)
    go getData(ch)
    //加time原因是讓2個go去執行, 因為主線程中的代碼是比goroutine先執行完畢的
    time.Sleep(100 * time.Second)
}
func sendData(ch chan string) {
        ch <- "Washington"
        ch <- "Tripoli"
        ch <- "London"
        ch <- "Beijing"
        ch <- "Tokio"
}
func getData(ch chan string) {
        var input string
        for {
        input = <-ch
        fmt.Println(input)
        }
}

for循環去遍歷chan

package main
import (
"fmt"
"time"
)
func main() {
    ch := make(chan string)
    go sendData(ch)
    go getData(ch)
    time.Sleep(100 * time.Second)
}
func sendData(ch chan string) {
    ch <- "Washington"
    ch <- "Tripoli"
    ch <- "London"
    ch <- "Beijing"
    ch <- "Tokio"
}
func getData(ch chan string) {
    for input := range ch {
        fmt.Println(input)
    }
}

Channel關閉            

  1. 使用內置函數close進行關閉,chan關閉后。for range遍歷chan中已經存在的元素后結束

    1. func rangegetData(ch chan string)  {
          //另外用法,用來取管道中的數據
          //
          for input:=range ch{
              fmt.Printf("#%v\n",input)
          }
      }
  2. 使用內置函數close進行關閉,chan關閉后沒有使用for range的寫法需要使用,v,ok := <-ch 進行判斷chan是否關閉

    1. func getData(ch chan  string)  {
          //死循環
          for {
              input,ok :=<- ch
              //ok是判斷管道是否關閉
              if !ok{
                  fmt.Printf("管道關閉")
                  break
              }
              fmt.Printf("channe_read:%s\n",input)
          }
      }


    2. 進階栗子:

      1. func consumer(ch  <-chan string){
           for{
              str,ok := <- ch
              if !ok{
                 fmt.Printf("ch is closed!!")
                 break
              }
              fmt.Printf("value is %s \n",str)
           }
        }
        func main(){
        
        var ch chan string = make(chan string)
        consumer(ch)}


Channel只讀/只寫

只讀chan聲明

var 變量名字 <-chan int
var readChan <-chan int

只寫chan聲明

var 變量名字 chan<-int
var writeChan chan<-int

Channel Select管理

注意:調度是隨機的

一個簡單的栗子:

for {
   str := fmt.Sprintf("hello %d",i)
   //select來管理管道
   //調度是隨機的,
   select {
   case ch <- str:
   case exit = <-exitChan:
   }
   if exit{
      fmt.Printf("user notify exitedd!!\n")
      break
   }
}

定時器

規定時間后運行代碼

package main

import (
   "time"
   "fmt"
)

func run()  {
    t:=time.NewTicker(time.Second * 5)
    //t.C 是一個管道
    for v:=range t.C{
      fmt.Println("hello",v)
    }

}
func main()  {
   run()
}

只運行一次:

package main
import (
   "fmt"
   "time"
)
func main() {

   select {
      case <- time.After(time.Second):
      fmt.Println("after")
   }
}

超時控制 (可以用于檢測類似Mysql查詢超時等):

package main

import (
   "time"
   "fmt"
)

func queryDB(ch chan  int)  {
   time.Sleep(time.Second * 1000)
   ch <- 100
}
func main()  {
   ch :=make(chan int,5)
   go queryDB(ch)
   //設置主線程運行時間,
   t := time.NewTicker(time.Second * 5 )
   //隨機調度
   select {
       //去ch中取,是否有數據,
      case <-ch:
         fmt.Println("reslt")
       
      case <-t.C:
         fmt.Printf("timeout!!!")
   }

}

讀寫鎖:

寫鎖:sync.Mutex 是互斥鎖, 多個線程修改數據的適合,只有一個線程可以修改

讀鎖:sync.RWMutex 讀鎖,多個線程同時讀一份數據,可以并發的去執行


Go中使用recover

應?場景,如果某個goroutine panic了,?且這個goroutine??沒有捕獲(recover),那么整個進程就會掛掉。所以,好的習慣是每當go??個goroutine,就需要寫下recover

package main

import (
   "time"
   "fmt"
)

func calc()  {
   //捕獲異常
   //必須寫在最前面
   defer func() {
      error :=recover()
      if error !=nil{
         fmt.Println(error)
      }


   }()
   var p *int
   //p = new(int)
   *p = 100
}
func main()  {
   go calc()
   time.Sleep(time.Second * 2)
   fmt.Println("---")
}

單元測試

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

崇左市| 监利县| 罗甸县| 平陆县| 桦南县| 利川市| 宁河县| 水富县| 会昌县| 朔州市| 汝城县| 时尚| 三原县| 邓州市| 长海县| 泸定县| 温州市| 新津县| 渭源县| 杭锦旗| 垦利县| 亚东县| 屏东市| 辽宁省| 长葛市| 邹平县| 安徽省| 和龙市| 吉木乃县| 福海县| 岳池县| 南充市| 平顶山市| 鲁甸县| 浙江省| 五大连池市| 十堰市| 德格县| 中西区| 中牟县| 民勤县|