package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"runtime"
"sync"
"time"
)
// 定义任务队列
var waitgroup sync.WaitGroup
func xtgxiso(num int) {
//fmt.Println(num)
db, err := sql.Open("mysql", "root:Abcdef@123456@tcp(127.0.0.1:3306)/good_job?charset=utf8")
if err != nil {
fmt.Println(err)
}
defer db.Close()
rows, err := db.Query("select sleep(1) as a")
if err != nil {
fmt.Println(err)
}
defer rows.Close()
var a string
for rows.Next() {
err = rows.Scan(&a)
if err != nil {
fmt.Println(err)
} else {
//fmt.Println(a)
}
}
waitgroup.Done() //任务完成,将任务队列中的任务数量-1,其实.Done就是.Add(-1)
}
func main() {
//记录开始时间
start := time.Now()
//设置最大的可同时使用线程数
runtime.GOMAXPROCS(1)
for i := 1; i <= 10; i++ {
waitgroup.Add(1) //每创建一个goroutine,就把任务队列中任务的数量+1
// xtgxiso(i)
go xtgxiso(i)
}
waitgroup.Wait() //Wait()这里会发生阻塞,直到队列中所有的任务结束就会解除阻塞
//记录结束时间
end := time.Now()
//输出执行时间,单位为秒。
fmt.Println(end.Sub(start).Seconds())
}
// 顺序执行
10.1454757
// 协程
1.0188696
这个程序是执行十次”select sleep(1) as a“.如果是顺序阻塞执行的话,执行时间肯定是10s以上,而我们用的协程不会有这种情况。
我们可以修改“runtime.GOMAXPROCS(1)”来设置最大可同时执行的线程数,对比结果发现,都是1s多点,有时多线程反而会比单线程慢些,这是为什么呢?
这是因为这个程序是IO为主的,启用多线程反而有上下文切换,所以对于以涉及IO操作的主的程序启用多线程对于加速程序意义不大。
runtime.GOMAXPROCS(1) 保证了mysql的操作(golang底层走的是非阻塞io)都在一个线程上执行,也就没有了cpu在多个线程之间来回调度。
那么什么程序启用多线程呢?我们来看如下程序:
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
// 定义任务队列
var waitgroup2 sync.WaitGroup
func xtgxiso2(num int) {
for i := 1; i <= 1000000000; i++ {
num = num + i
num = num - i
num = num * i
num = num / i
}
waitgroup2.Done() //任务完成,将任务队列中的任务数量-1,其实.Done就是.Add(-1)
}
func main() {
start := time.Now()
//设置最大的可同时使用的线程数
runtime.GOMAXPROCS(16)
for i := 1; i <= 10; i++ {
waitgroup2.Add(1) //每创建一个goroutine,就把任务队列中任务的数量+1
go xtgxiso2(i)
}
waitgroup2.Wait() //Wait()这里会发生阻塞,直到队列中所有的任务结束就会解除阻塞 线//记录结束时间
end := time.Now()
//输出执行时间,单位为秒。
fmt.Println(end.Sub(start).Seconds())
}
4.7383003
0.7276601
对比结果发现,多线程比单线程快,所以对于CPU的运行上,多线程运行加速效果是很明显的.
原文