1. package main
    2. import (
    3. "database/sql"
    4. "fmt"
    5. _ "github.com/go-sql-driver/mysql"
    6. "runtime"
    7. "sync"
    8. "time"
    9. )
    10. // 定义任务队列
    11. var waitgroup sync.WaitGroup
    12. func xtgxiso(num int) {
    13. //fmt.Println(num)
    14. db, err := sql.Open("mysql", "root:Abcdef@123456@tcp(127.0.0.1:3306)/good_job?charset=utf8")
    15. if err != nil {
    16. fmt.Println(err)
    17. }
    18. defer db.Close()
    19. rows, err := db.Query("select sleep(1) as a")
    20. if err != nil {
    21. fmt.Println(err)
    22. }
    23. defer rows.Close()
    24. var a string
    25. for rows.Next() {
    26. err = rows.Scan(&a)
    27. if err != nil {
    28. fmt.Println(err)
    29. } else {
    30. //fmt.Println(a)
    31. }
    32. }
    33. waitgroup.Done() //任务完成,将任务队列中的任务数量-1,其实.Done就是.Add(-1)
    34. }
    35. func main() {
    36. //记录开始时间
    37. start := time.Now()
    38. //设置最大的可同时使用线程数
    39. runtime.GOMAXPROCS(1)
    40. for i := 1; i <= 10; i++ {
    41. waitgroup.Add(1) //每创建一个goroutine,就把任务队列中任务的数量+1
    42. // xtgxiso(i)
    43. go xtgxiso(i)
    44. }
    45. waitgroup.Wait() //Wait()这里会发生阻塞,直到队列中所有的任务结束就会解除阻塞
    46. //记录结束时间
    47. end := time.Now()
    48. //输出执行时间,单位为秒。
    49. fmt.Println(end.Sub(start).Seconds())
    50. }
    1. // 顺序执行
    2. 10.1454757
    3. // 协程
    4. 1.0188696

    这个程序是执行十次”select sleep(1) as a“.如果是顺序阻塞执行的话,执行时间肯定是10s以上,而我们用的协程不会有这种情况。

    我们可以修改“runtime.GOMAXPROCS(1)”来设置最大可同时执行的线程数,对比结果发现,都是1s多点,有时多线程反而会比单线程慢些,这是为什么呢?

    这是因为这个程序是IO为主的,启用多线程反而有上下文切换,所以对于以涉及IO操作的主的程序启用多线程对于加速程序意义不大。

    runtime.GOMAXPROCS(1) 保证了mysql的操作(golang底层走的是非阻塞io)都在一个线程上执行,也就没有了cpu在多个线程之间来回调度。

    那么什么程序启用多线程呢?我们来看如下程序:

    1. package main
    2. import (
    3. "fmt"
    4. "runtime"
    5. "sync"
    6. "time"
    7. )
    8. // 定义任务队列
    9. var waitgroup2 sync.WaitGroup
    10. func xtgxiso2(num int) {
    11. for i := 1; i <= 1000000000; i++ {
    12. num = num + i
    13. num = num - i
    14. num = num * i
    15. num = num / i
    16. }
    17. waitgroup2.Done() //任务完成,将任务队列中的任务数量-1,其实.Done就是.Add(-1)
    18. }
    19. func main() {
    20. start := time.Now()
    21. //设置最大的可同时使用的线程数
    22. runtime.GOMAXPROCS(16)
    23. for i := 1; i <= 10; i++ {
    24. waitgroup2.Add(1) //每创建一个goroutine,就把任务队列中任务的数量+1
    25. go xtgxiso2(i)
    26. }
    27. waitgroup2.Wait() //Wait()这里会发生阻塞,直到队列中所有的任务结束就会解除阻塞 线//记录结束时间
    28. end := time.Now()
    29. //输出执行时间,单位为秒。
    30. fmt.Println(end.Sub(start).Seconds())
    31. }
    1. 4.7383003
    2. 0.7276601

    对比结果发现,多线程比单线程快,所以对于CPU的运行上,多线程运行加速效果是很明显的.

    原文