107.【并发与标准库】(三)

简介: 107.【并发与标准库】

6.并发编程之channel的遍历

(1).放入的比读取的少

分为两种情况: 是否关闭资源

1.没有关闭管道资源

package main
import "fmt"
var c = make(chan int)
func main() {
  go func() { // 添加go 目的主要是为了同步
    for i := 0; i < 2; i++ {
      c <- i
    }
  }()
  // 假如就写入两个那么读取三个会有什么样的结果?
  for i := 0; i < 3; i++ {
    r := <-c
    fmt.Printf("%v\t", r)
  }
}

会产生死锁反应

2.关闭管道资源

package main
import "fmt"
var c = make(chan int)
func main() {
  go func() { // 添加go 目的主要是为了同步
    for i := 0; i < 2; i++ {
      c <- i
    }
    close(c) //--------------------关闭资源,会默认为类型的值
  }()
  // 假如就写入两个那么读取三个会有什么样的结果?
  for i := 0; i < 3; i++ {
    r := <-c
    fmt.Printf("%v\t", r)
  }
}

不会报错

(2).三种遍历方式

1.第一种for循环进行遍历

package main
import "fmt"
var c = make(chan int)
func main() {
  go func() { // 添加go 目的主要是为了同步
    for i := 0; i < 2; i++ {
      c <- i
    }
    close(c) //--------------------关闭资源,会默认为类型的值
  }()
  // 假如就写入两个那么读取三个会有什么样的结果?
  for i := 0; i < 3; i++ {
    r := <-c
    fmt.Printf("%v\t", r)
  }
}

2.range遍历

遍历管道的值的话,只有一个v值,没有下标

package main
import "fmt"
var c = make(chan int)
func main() {
  go func() { // 添加go 目的主要是为了同步
    for i := 0; i < 2; i++ {
      c <- i
    }
    close(c) //--------------------关闭资源,会默认为类型的值
  }()
  // 假如就写入两个那么读取三个会有什么样的结果?
  for v := range c {  //  只有一个
    fmt.Printf("%v\t", v)
  }
}

3.利用for if

package main
import "fmt"
var c = make(chan int)
func main() {
  go func() { // 添加go 目的主要是为了同步
    for i := 0; i < 2; i++ {
      c <- i
    }
    close(c) //--------------------关闭资源,会默认为类型的值
  }()
  // 假如就写入两个那么读取三个会有什么样的结果?
  for true {
    v, ok := <-c // 这个是判断是否存在值,如果存在那么就为true
    if ok {
      fmt.Printf("%v\t", v)
    } else {
      break
    }
  }
}

7.并发编程之select

(1).基础介绍
  1. select是Go中的一个控制层结构,类似于switch 语句,用于处理异步IO操作。select监听case语句中channel的读写操作,当case中的channel读写操作为非阻塞状态(即能读写)时,将会触发相应的动作。

1.select 中的case语句必须是一个channel操作

2.select 中的default子句总是可以运行的

  1. 如果有多个case都可以运行,select会随机公平地选出一个执行,其他不会执行
  2. 如果没有可运行地 case 语句,且有 default 语句,那么就会执行 default地动作
  3. 如果没有可运行地case语句,且没有default语句,select 将阻塞,直到某个case通信可以运行.
(2).select测试
package main
import (
  "fmt"
  "time"
)
var chanInt = make(chan int)
var chanString = make(chan string)
func main() {
  go func() {  //开启一个协助
    chanInt <- 100
    chanString <- "hello"
    defer close(chanString)
    defer close(chanInt)
  }()
  for true {
    select {
    case r := <-chanInt:
      fmt.Printf("%v\n", r)
    case r := <-chanString:
      fmt.Printf("%v\n", r)
    default:
      println("default....")
    }
    time.Sleep(time.Second)
  }
}

输出结果不固定: 三个顺序不定。

2.假如没有default并且没有case 那么就会报死锁

前提是没有关闭资源,关闭资源就不会报死锁

package main
import (
  "fmt"
  "time"
)
var chanInt = make(chan int)
var chanString = make(chan string)
func main() {
  go func() {
    chanInt <- 100
    chanString <- "hello"
    //defer close(chanString)
    //defer close(chanInt)
  }()
  for true {
    select {
    case r := <-chanInt:
      fmt.Printf("%v\n", r)
    case r := <-chanString:
      fmt.Printf("%v\n", r)
    }
    time.Sleep(time.Second)
  }
}

8.并发编程之Timer

(1).基础介绍

Timer顾名思义就是定时器的意思。可以实现一些定时操作,器内部也是通过channel来实现的。

1.第一种定义方式
time.NewTime()   //进行创建
2.第二种定义方式
time.After()  //进行创建
(2).定时器的实列
  1. 利用NerTime() 指定时间后再执行
package main
import (
  "fmt"
  "time"
)
func main() {
  // 1.第一种定义定时器
  timer := time.NewTimer(time.Second * 2) //设置指定时间后执行管道读出
  fmt.Printf("现在的时间是: %v\n", time.Now())
  t1 := <-timer.C //阻塞的,指定时间到了便会读出
  fmt.Printf("管道读出的时间是: %v\n", t1)
}

  1. 不设置变量名进行定时阻塞
package main
import (
  "fmt"
  "time"
)
func main() {
   1.第一种定义定时器
  //timer := time.NewTimer(time.Second * 2) //设置指定时间后执行管道读出
  //fmt.Printf("现在的时间是: %v\n", time.Now())
  //t1 := <-timer.C //阻塞的,指定时间到了便会读出
  //fmt.Printf("管道读出的时间是: %v\n", t1)
  fmt.Printf("现在的时间是: %v\n", time.Now())
  timer := time.NewTimer(time.Second * 2) //设置指定时间后执行管道读出
  <-timer.C   //这里也会等待两秒钟
  fmt.Printf("现在的时间是: %v\n", time.Now())
}

  1. After创建定时器
package main
import (
  "fmt"
  "time"
)
func main() {
   1.第一种定义定时器
  //timer := time.NewTimer(time.Second * 2) //设置指定时间后执行管道读出
  //fmt.Printf("现在的时间是: %v\n", time.Now())
  //t1 := <-timer.C //阻塞的,指定时间到了便会读出
  //fmt.Printf("管道读出的时间是: %v\n", t1)
  //fmt.Printf("现在的时间是: %v\n", time.Now())
  //timer := time.NewTimer(time.Second * 2) //设置指定时间后执行管道读出
  //<-timer.C
  //fmt.Printf("现在的时间是: %v\n", time.Now())
  fmt.Printf("现在的时间是: %v\n", time.Now())
  <-time.After(time.Second * 2)  //利用After进行创建定时器
  fmt.Printf("现在的时间是: %v\n", time.Now())
}

相关文章
|
4月前
|
算法 数据处理 Python
Python并发编程:解密异步IO与多线程
本文将深入探讨Python中的并发编程技术,重点介绍异步IO和多线程两种常见的并发模型。通过对比它们的特点、适用场景和实现方式,帮助读者更好地理解并发编程的核心概念,并掌握在不同场景下选择合适的并发模型的方法。
|
12月前
|
缓存 Go
107.【并发与标准库】(二)
107.【并发与标准库】
38 0
|
12月前
|
缓存 Go C语言
107.【并发与标准库】(七)
107.【并发与标准库】
45 0
|
4月前
|
数据采集 数据库 C++
python并发编程:并发编程中是选择多线程呢?还是多进程呢?还是多协程呢?
python并发编程:并发编程中是选择多线程呢?还是多进程呢?还是多协程呢?
46 0
|
12月前
|
缓存 索引
107.【并发与标准库】(九)
107.【并发与标准库】
32 0
|
10月前
|
编译器 Linux 调度
|
15天前
|
消息中间件 存储 安全
python多进程并发编程之互斥锁与进程间的通信
python多进程并发编程之互斥锁与进程间的通信
|
2月前
|
数据采集 算法 数据处理
Python中的并发编程:异步IO与多线程对比分析
传统的多线程编程在Python中因为全局解释器锁(GIL)的存在受到限制,导致多线程并不能充分利用多核处理器的优势。本文将探讨Python中的异步IO编程与多线程编程的差异与优劣,并分析适合的应用场景。
|
3月前
|
并行计算 API Python
Python中的并发编程(1)并发相关概念
Python中的并发编程(1)并发相关概念
|
4月前
|
消息中间件 程序员 调度
Python并发编程:利用多线程提升程序性能
本文探讨了Python中的并发编程技术,重点介绍了如何利用多线程提升程序性能。通过分析多线程的原理和实现方式,以及线程间的通信和同步方法,读者可以了解如何在Python中编写高效的并发程序,提升程序的执行效率和响应速度。