package mainimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql""runtime""sync""time")// 定义任务队列var waitgroup sync.WaitGroupfunc 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 stringfor 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 mainimport ("fmt""runtime""sync""time")// 定义任务队列var waitgroup2 sync.WaitGroupfunc xtgxiso2(num int) {for i := 1; i <= 1000000000; i++ {num = num + inum = num - inum = num * inum = 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,就把任务队列中任务的数量+1go xtgxiso2(i)}waitgroup2.Wait() //Wait()这里会发生阻塞,直到队列中所有的任务结束就会解除阻塞 线//记录结束时间end := time.Now()//输出执行时间,单位为秒。fmt.Println(end.Sub(start).Seconds())}
4.73830030.7276601
对比结果发现,多线程比单线程快,所以对于CPU的运行上,多线程运行加速效果是很明显的.
原文
