golang中四种方式实现子goroutine与主协程的同步

如何实现子goroutine与主线程的同步

  • 第一种方式:time.sleep(),这种方式很太死板,就不演示了。
  • 第二种方式:使用channel机制,每个goroutine传一个channel进去然后往里写数据,在再主线程中读取这些channel,直到全部读到数据了子goroutine也就全部运行完了,那么主goroutine也就可以结束了。这种模式是子线程去通知主线程结束。
package main

import (
    "fmt"
)

func main() {
    var chanTest = make(chan int)
    var chanMain = make(chan int)

    go func() {
        for i := 0; i < 20; i++ {
            chanTest <- i
            fmt.Println("生产者写入数据", i)
        }
        close(chanTest)
    }()

    go func() {
        for v := range chanTest {
            fmt.Println("\t消费者读出数据", v)

        }

        chanMain <- 666
    }()

    go func() {
        for v := range chanTest {
            fmt.Println("\t\t消费者读出数据", v)

        }
        chanMain <- 666

    }()

    <-chanMain
    <-chanMain

}
  • 第三种方式:使用context中cancel函数,这种模式是主线程去通知子线程结束。
package main

import (
    "context"
    "fmt"
    "time"
)

func gen(ctx context.Context) <-chan int {
    dst := make(chan int)
    n := 1
    go func() {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("i exited")
                return // returning not to leak the goroutine
            case dst <- n:
                n++
            }
        }
    }()
    return dst
}

func test() {

    ctx, cancel := context.WithCancel(context.Background())
    defer cancel() // cancel when we are finished consuming integers
    intChan := gen(ctx)
    for n := range intChan {
        fmt.Println(n)
        if n == 5 {
            break
        }
    }
}
func main() {
    test()
    time.Sleep(time.Hour)
}
  • 第四种方式:sync.WaitGroup模式,Add方法设置等待子goroutine的数量,使用Done方法设置等待子goroutine的数量减1,当等待的数量等于0时,Wait函数返回。
//使用golang中sync.WaitGroup来实现协程同步  

package main  

import (
    "fmt"
    "net/http"
    "io/ioutil"
    "time"
    "os"
    "sync"
)  

var waitGroup = new(sync.WaitGroup)
func download(i int ){
        url := fmt.Sprintf("http://pic2016.ytqmx.com:82/2016/0919/41/%d.jpg", i)
        fmt.Printf("开始下载:%s\n", url)
        res,err := http.Get(url)
        if err != nil || res.StatusCode != 200{
            fmt.Printf("下载失败:%s", res.Request.URL)
        }
        fmt.Printf("开始读取文件内容,url=%s\n", url)
        data ,err2 := ioutil.ReadAll(res.Body)
        if err2 != nil {
            fmt.Printf("读取数据失败")
        }  

        ioutil.WriteFile(fmt.Sprintf("pic2016/1_%d.jpg", i), data, 0644)
        //计数器-1
        waitGroup.Done()
}  

func main()  {
    //创建多个协程,同时下载多个图片
    os.MkdirAll("pic2016", 0666)
    now := time.Now()  

    for i :=1; i<24; i++ {
        //计数器+1
        waitGroup.Add(1)
        go download(i)
    }  

    //等待所有协程操作完成
    waitGroup.Wait()
    fmt.Printf("下载总时间:%v\n", time.Now().Sub(now))
} 

原文地址:https://www.cnblogs.com/node-js/p/8964171.html

时间: 2024-08-16 04:34:52

golang中四种方式实现子goroutine与主协程的同步的相关文章

Android中多线程的使用四种方式最全总结

当我们启动一个App的时候,Android系统会启动一个Linux Process,该Process包含一个Thread,称为UI Thread或Main Thread.通常一个应用的所有组件都运行在这一个Process中,当然,你可以通过修改四大组件在Manifest.xml中的代码块(<activity><service><provider><receiver>)中的android:process属性指定其运行在不同的process中.当一个组件在启动的

JAVA中集合输出的四种方式

在JAVA中Collection输出有四种方式,分别如下: 一) Iterator输出. 该方式适用于Collection的所有子类. public class Hello { public static void main(String[] args) throws Exception { Set<Person> javaProgramers = new HashSet<Person>(); javaProgramers.add(new Person("aaron&qu

Struts2中访问web元素的四种方式

Struts2中访问web元素的四种方式如下: 通过ActionContext来访问Map类型的request.session.application对象. 通过实现RequestAware.SessionAware.ApplicationAware接口来访问Map类型的request.session.application对象(IoC方式). 通过ServletActionContext来访问Servlet API类型的HttpServletRequest. HttpSession. Serv

C#_批量插入数据到Sqlserver中的四种方式

先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记录的ID的值然后再进行加1运算要少.而如果存在索引的情况下,每次插入记录都会进行索引重建,这是非常耗性能的.如果表中无可避免的存在索引,我们可以通过先删除索引,然后批量插入,最后再重建索引的方式来提高效率. create database CarSYS;    go    use CarSYS;  

Webform中Repeater控件--绑定嵌入C#代码四种方式

网页里面嵌入C#代码用的是<% %>,嵌入php代码<?php ?> 绑定数据的四种方式: 1.直接绑定 <%#Eval("Code") %> 2.调用函数 <%#ShowSex()%> 3.显示外键关系列 <%#Eval("Nation1.Name") %> 4.格式化显示 <%#Eval("Birthday","{0:yyyy年MM月dd日}") %>

JavaScript中四种不同的属性检测方式比较

JavaScript中四种不同的属性检测方式比较 1. 用in方法 var o = {x:1}; "x" in o; //true "y" in o; //false "toString" in o; //true,继承属性可以被检测到 "toString" in Object.prototype; //true,不可枚举的属性可以被检测到 2. hasOwnProperty()方法 var o = {x:1}; o.hasO

Action中取得request,session的四种方式

在Struts2中,从Action中取得request,session的对象进行应用是开发中的必需步骤,那么如何从Action中取得这些对象呢?Struts2为我们提供了四种方式.分别为servlet 不相关的 非IoC 取得Request等对象的方式servlet 不相关的 IoC 取得Request等对象的方式servlet 相关的 非IoC 取得Request等对象的方式servlet 相关的 IoC 取得Request等对象的方式以下分别叙述. 首先请看struts.xml文件文件内容:

C# 字符串拼接性能探索 c#中+、string.Concat、string.Format、StringBuilder.Append四种方式进行字符串拼接时的性能

本文通过ANTS Memory Profiler工具探索c#中+.string.Concat.string.Format.StringBuilder.Append四种方式进行字符串拼接时的性能. 本文涉及程序为.NET Core 2.0控制台应用程序. 一.常量字符串拼接 private static void TestPerformance(Action action, int times) { Stopwatch sw = new Stopwatch(); sw.Start(); for(i

Java中遍历Map的四种方式

Demo如下 Map<String, String> map = new HashMap<>(); map.put("key1","data1"); map.put("key2","data2"); map.put("key3","data3"); //第一种方式 System.out.println("通过Map.keySet(),遍历key,valu