zoukankan      html  css  js  c++  java
  • Go常见并发任务

    仅执行一次

    比如实现线程安全的单利模式
    除了用 sync.Once 实现,我们还可以利用 package 的 init() 函数去实现

    package once_test
    
    import (
    	"fmt"
    	"sync"
    	"testing"
    	"unsafe"
    )
    
    type Singleton struct {}
    
    var singleInstance *Singleton
    var once sync.Once
    
    func GetSingletonObj() *Singleton {
    	once.Do(func() {
    		fmt.Println("Create Obj")
    		singleInstance = new(Singleton)
    	})
    	return singleInstance
    }
    
    func TestGetSingletonObj(t *testing.T) {
    	var wg sync.WaitGroup
    	for i := 0; i < 10; i++ {
    		wg.Add(1)
    		go func() {
    			obj := GetSingletonObj()
    			fmt.Printf("%x
    ", unsafe.Pointer(obj)) // 将16进制转为
    			wg.Done()
    		}()
    	}
    	wg.Wait()
    }
    

    仅需任意任务完成

    比如我们去同不同的服务器上取相同的数据,只要有一个返回就结束全部任务。
    思路:我直接获取buffer channel的第一个值就可以了

    package any_reply_test
    
    import (
    	"fmt"
    	"runtime"
    	"testing"
    	"time"
    )
    
    func runTask(id int) string {
    	time.Sleep(10 * time.Millisecond)
    	return fmt.Sprintf("The result is from %d", id)
    }
    
    func FirstResponse() string {
    	numOfRunner := 10
    	ch := make(chan string, numOfRunner) // 必须为 buffer channel,不然会导致 goroutine 阻塞
    	for i := 0; i < numOfRunner; i++ {
    		go func(i int) {
    			ret := runTask(i)
    			ch <- ret
    		}(i)
    	}
    	return <-ch
    }
    
    func TestFirstResponse(t *testing.T) {
    	t.Log("Before:", runtime.NumGoroutine()) // 当前系统中的协程数,2
    	t.Log(FirstResponse())
    	time.Sleep(time.Second * 1)
    	t.Log("After:", runtime.NumGoroutine()) // 当前系统中的协程数,2
    }
    

    所有任务都完成

    可以使用 sync.WaitGroup,还有利用 channel 的实现

    package all_rep_test
    
    import (
    	"fmt"
    	"runtime"
    	"testing"
    	"time"
    )
    
    func runTask(id int) string {
    	time.Sleep(10 * time.Millisecond)
    	return fmt.Sprintf("The result if from %d", id)
    }
    
    func AllResponse() string {
    	numOfRunner := 10
    	ch := make(chan string, numOfRunner)
    	for i := 0; i < numOfRunner; i++ {
    		go func(i int) {
    			ret := runTask(i)
    			ch <- ret
    		}(i)
    	}
    	finalRet := ""
    	for j := 0; j < numOfRunner; j++ {
    		finalRet += <-ch + "
    "
    	}
    	return finalRet
    }
    
    func TestAllResponse(t *testing.T) {
    	t.Log("Before:", runtime.NumGoroutine())
    	t.Log(AllResponse())
    	time.Sleep(time.Second * 1)
    	t.Log("After:", runtime.NumGoroutine())
    }
    
  • 相关阅读:
    apache 问题 You don't have permission to access /test.php on this server 解决方法
    setTimeout和setInterval实现定时器的区别
    视图Ext.Viewport和窗口Ext.Window用法
    JavaScript设置Cookie
    布局Layout
    html中select标签刷新后不回到默认值而是保持之前选择值
    设置session失效的几种方法
    面板Ext.Panel使用
    树TreePanel
    让html元素随浏览器的大小自适应垂直居中
  • 原文地址:https://www.cnblogs.com/wuyongqiang/p/12126431.html
Copyright © 2011-2022 走看看