请问,怎样把京东E卡上的钱京东余额转到银行卡卡上

Golang 并发模式:超时和继续 Go Concurrency Patterns: Timing out, moving on_go语言_ThinkSAAS
Golang 并发模式:超时和继续 Go Concurrency Patterns: Timing out, moving on
Golang 并发模式:超时和继续 Go Concurrency Patterns: Timing out, moving on
内容来源: 网络
翻译自 Go Blog。原文地址:
并发编程有自己的一些习惯用语,超时就是其中之一。虽然 Golang 的管道并没有直接支持超时,但是实现起来并不难。假设遇到了这样一种场景:在从 管道 ch 中取值之前至少等待 1 秒钟。我们可以创建一个管道用来传递信号,开启一个协程休眠一秒钟,然后给管道传递一个值。
timeout := make(chan bool, 1)
go func() {
time.Sleep(1 * time.Second)
timeout &- true
然后就可以使用一个 select 语句来从 timeout 或者 ch 管道中获取数据。如果 ch 管道在 1 秒钟之后还没有返回数据,超时的判断条件就会触发 ch 的读操作将会被抛弃掉。
case &-ch:
// a read from ch has occurred
case &-timeout:
// the read from ch has timed out
timeout 管道的缓冲区空间为 1,因此 timeout 协程将会在发送消息到管道之后退出执行。协程并不知道(也不关心)管道中的值是否被接受。因此,即使 ch 管道先于 timeout 管道返回了,timeout 协程也不会永久等待。timeout 管道最终会被垃圾回收机制回收掉。
(在上面的示例中我们使用了 time.Sleep 方法来演示协程和管道的机制,但是在真实的代码中应该用 time.After 方法,该方法返回了一个管道,并且会在参数指定的时间之后向管道中写入一个消息)
下面我们来看这种模式的另外一个变种。我们需要从多个分片数据库中同时取数据,程序只需要其中最先返回的那个数据。
下面的 Query 方法接受两个参数:一个数据库链接的切片和一个数据库查询语句。该方法将平行查询所有数据库并返回第一个接受到的响应结果。
func Query(conns []Conn, query string) Result {
ch := make(chan Result, 1)
for _, conn := range conns {
go func(c Conn) {
case ch &- c.DoQuery(query):
return &-ch
在上面这个例子中,go 关键字后的闭包实现了一个非阻塞式的查询请求,因为 DoQuery 方法被放到了带 default 分支的 select 语句中。假如 DoQuery 方法没有立即返回,default 分支将会被选中执行。让查询请求非阻塞保证了 for 循环中创建的协程不会一直阻塞。另外,假如在主方法从 ch 管道中取出值并返回结果之前有第二个查询结果返回了,管道 ch 的写操作将会失败,因为管道并未就绪。
上面描述的问题其实是“竞争关系”的一种典型例子,示例代码只是一种很通俗的解决方案。我们只是中管道上设定了缓冲区(通过在管道的 make 方法中传入第二个参数),保证了第一个写入者能够有空间来写入值。这种策略保证了管道的第一次写入一定会成功,无论代码以何种顺序执行,第一个写入的值将会被当作最终的返回值。
Go 的协程之前可以进行复杂的协作,以上两个例子就是最简单的证明。内容来源:
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信PHP与Golang如何通信? - 简书
PHP与Golang如何通信?
最近遇到的一个场景:php项目中需要使用一个第三方的功能(),而github上面恰好有一个用Golang写好的类库。那么问题就来了,要如何实现不同语言之间的通信呢?
常规的方案:
用Golang写一个http/TCP服务,php通过http/TCP与Golang通信
将Golang经过较多封装,做为php扩展。
PHP通过系统命令,调取Golang的可执行文件
存在的问题:
http请求,网络I/O将会消耗大量时间
需要封装大量代码
PHP每调取一次Golang程序,就需要一次初始化,时间消耗很多
优化目标:
Golang程序只初始化一次(因为初始化很耗时)
所有请求不需要走网络
尽量不大量修改代码
解决方案:
简单的Golang封装,将第三方类库编译生成为一个可执行文件
PHP与Golang通过双向管道通信
使用双向管道通信优势:
1:只需要对原有Golang类库进行很少的封装2:性能最佳 (IPC通信是进程间通信的最佳途径)3:不需要走网络请求,节约大量时间4:程序只需初始化一次,并一直保持在内存中
具体实现步骤:
1:类库中的原始调取demo
package main
"/yanyiwu/gojieba"
func main() {
x := gojieba.NewJieba()
defer x.Free()
s := "小明硕士毕业于中国科学院计算所,后在日本京都大学深造"
words := x.CutForSearch(s, true)
fmt.Println(strings.Join(words, "/"))
保存文件为main.go,就可以运行
2:调整后代码为:
package main
"/yanyiwu/gojieba"
func main() {
x := gojieba.NewJieba(
"/data/tmp/jiebaDict/jieba.dict.utf8",
"/data/tmp/jiebaDict/hmm_model.utf8",
"/data/tmp/jiebaDict/user.dict.utf8"
defer x.Free()
inputReader := bufio.NewReader(os.Stdin)
s, err := inputReader.ReadString('\n')
if err != nil && err == io.EOF {
s = strings.TrimSpace(s)
if s != "" {
words := x.CutForSearch(s, true)
fmt.Println(strings.Join(words, " "))
fmt.Println("get empty \n")
只需要简单的几行调整,即可实现:从标准输入接收字符串,经过分词再输出 测试:
# go build test
# //等待用户输入,输入”这是一个测试“
# 这是 一个 测试 //程序
3:使用cat与Golang通信做简单测试
//准备一个title.txt,每行是一句文本
# cat title.txt | ./test
正常输出,表示cat已经可以和Golang正常交互了
4:PHP与Golang通信  以上所示的cat与Golang通信,使用的是单向管道。即:只能从cat向Golang传入数据,Golang输出的数据并没有传回给cat,而是直接输出到屏幕。但文中的需求是:php与Golang通信。即php要传数据给Golang,同时Golang也必须把执行结果返回给php。因此,需要引入双向管道。  在PHP中管道的使用:popen("/path/test"),具体就不展开说了,因为此方法解决不了文中的问题。
双向管道:
$descriptorspec = array(
0 =& array("pipe", "r"),
1 =& array("pipe", "w")
$handle = proc_open(
'/webroot/go/src/test/test',
$descriptorspec,
fwrite($pipes['0'], "这是一个测试文本\n");
echo fgets($pipes[1]);
解释:使用proc_open打开一个进程,调用Golang程序。同时返回一个双向管道pipes数组,php向$pipe['0']中写数据,从$pipe['1']中读数据。
好吧,也许你已经发现,我是标题档,这里重点要讲的并不只是PHP与Golang如何通信。而是在介绍一种方法: 通过双向管道让任意语言通信。(所有语言都会实现管道相关内容)
通过对比测试,计算出各个流程占用的时间。下面提到的title.txt文件,包含100万行文本,每行文本是从b2b平台取的商品标题
1: 整体流程耗时time cat title.txt | ./test & /dev/null
耗时:14.819秒,消耗时间包含:
进程cat读出文本
通过管道将数据传入Golang
Golang处理数据,将结果返回到屏幕
2:计算分词函数耗时。方案:去除分词函数的调取,即:注释掉Golang源代码中的调取分词那行的代码time cat title.txt | ./test & /dev/null
耗时:1.817秒时间,消耗时间包含:
进程cat读出文本
通过管道将数据传入Golang
Golang处理数据,将结果返回到屏幕
分词耗时 =
(第一步耗时) - (以上命令所耗时) 分词耗时 : 14.819 - 1.817 = 13.002秒
3:测试cat进程与Golang进程之间通信所占时间time cat title.txt & /dev/null
耗时:0.015秒,消耗时间包含:
进程cat读出文本
通过管道将数据传入Golang
go处理数据,将结果返回到屏幕
管道通信耗时:(第二步耗时)
- (第三步耗时) 管道通信耗时: 1.817 - 0.015 = 1.802秒
4:PHP与Golang通信的时间消耗编写简单的php文件:
$descriptorspec = array(
0 =& array("pipe", "r"),
1 =& array("pipe", "w")
$handle = proc_open(
'/webroot/go/src/test/test',
$descriptorspec,
$fp = fopen("title.txt", "rb");
while (!feof($fp)) {
fwrite($pipes['0'], trim(fgets($fp))."\n");
echo fgets($pipes[1]);
fclose($pipes['0']);
fclose($pipes['1']);
proc_close($handle);
流程与上面基本一致,读出title.txt内容,通过双向管道传入Golang进程分词后,再返回给php (比上面的测试多一步:数据再通过管道返回)time php popen.php & /dev/null
耗时:24.037秒,消耗时间包含:
进程PHP读出文本
通过管道将数据传入Golang
Golang处理数据
Golang将返回结果再写入管道,PHP通过管道接收数据
将结果返回到屏幕
1 :整个分词过程中的耗时分布
使用cat控制逻辑耗时:
使用PHP控制逻辑耗时:
24.037 秒(比cat多一次管道通信)
单向管道通信耗时:
Golang中的分词函数耗时:
2:分词函数的性能: 单进程,100万商品标题分词,耗时13秒 以上时间只包括分词时间,不包括词典载入时间。但在本方案中,词典只载入一次,所以载入词典时间可以忽略(1秒左右)
3:PHP比cat慢 (这结论有点多余了,呵呵)语言层面慢: (24.037 - 1.8 - 14.819) / 14.819 = 50% 单进程对比测试的话,应该不会有哪个语言比cat更快。
相关问题:
1:以上Golang源码中写的是一个循环,也就是会一直从管道中读数据。那么存在一个问题:是不是php进程结束后,Golang的进程还会一直存在?
管道机制自身可解决此问题。管道提供两个接口:读、写。当写进程结束或者意外挂掉时,读进程也会报错,以上Golang源代码中的err逻辑就会执行,Golang进程结束。但如果PHP进程没有结束,只是暂时没有数据传入,此时Golang进程会一直等待。直到php结束后,Golang进程才会自动结束。
2:能否多个php进程并行读写同一个管道,Golang进程同时为其服务?
不可以。管道是单向的,如果多个进程同时向管道中写,那Golang的返回值就会错乱。可以多开几个Golang进程实现,每个php进程对应一个Golang进程。
最后,上面都是瞎扯的。如果你了解管道、双向管道,上面的解释对你基本没啥用。但如果你不了解管道,调试上面的代码没问题,但稍有修改就有可能掉坑里。哈哈,推荐一本书吧,《UNIX网络编程》卷一、二,都看一下,也许要看两个月,但很有必要!
多读书、多看报,少看网页,多睡觉!
关注公众号"web创新之路”,就有机会天天听我瞎哔哔~
专注技术,分享经验golang并发管道vs锁vsJava lock - language - ITeye论坛
golang并发管道vs锁vsJava lock
锁定老帖子
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
来自: 深圳
发表时间:&&
相关知识库:
最近学习golang,语法方面还好,sdk api还需要熟悉,另外就是并发的设计和使用得多用多深入才行。
昨天做一个多线程的小题目练习下,就是“3个线程分别打印ABC,要求顺序打印n次”,结果发现用sync.Mutex,在windows下的性能和java没法比啊,用chan性能倒是意料之中比较好,下面贴下代码和事件消耗。
软硬件环境
windows7 pro 32位,奔腾 cpu + 4g内存
go1.3 / jdk1.6
java代码(耗时0.180s):
import java.util.concurrent.locks.L
import java.util.concurrent.locks.ReentrantL
final Lock lock = new ReentrantLock()
int num = 0
// 分别打印100次
int maxNum = 297
def start = System.currentTimeMillis()
Thread.start{
while(num &=maxNum){
lock.lock()
if(num % 3 == 0){
println 'A'
lock.unlock()
Thread.start{
while(num &=maxNum){
lock.lock()
if(num % 3 == 1){
println 'B'
lock.unlock()
Thread.start{
while(num &=maxNum){
lock.lock()
if(num % 3 == 2){
println 'C'
lock.unlock()
if(num == 300)
println System.currentTimeMillis() - start
go代码(用lock,耗时24至32s——肯定是我哪里用错了,肯定的!!)
package main
import "fmt"
import "sync"
import "time"
var m *sync.Mutex = new(sync.Mutex)
var max = 300
func Print(content string, divNum int, wg *sync.WaitGroup){
if i % 3 == divNum {
fmt.Println(content)
m.Unlock()
func main(){
var wg sync.WaitGroup
start := time.Now()
go Print("A", 0, &wg)
go Print("B", 1, &wg)
go Print("C", 2, &wg)
duration := time.Since(start)
fmt.Println(duration.Seconds())
go代码用chan(耗时0.001s,100倍差距!!)
package main
// 打印100次
var num int = 100
// 用两个chan进行通知
func Print(content string, ch chan int, ch2 chan int, wg *sync.WaitGroup){
if "A" == content {
// 第一个,所以要接收最后一个chan,但是不打印
for i := 0; i &= i++ {
if i & num{
fmt.Println(content)
for i := 0; i & i++ {
fmt.Println(content)
func main() {
var wg sync.WaitGroup
ch1 := make(chan int)
ch2 := make(chan int)
ch3 := make(chan int)
start := time.Now()
go Print("A", ch1, ch3, &wg)
go Print("B", ch2, ch1, &wg)
go Print("C", ch3, ch2, &wg)
duration := time.Since(start)
fmt.Println(duration.Seconds())
测试的是java lock 0.188s,go chan 0.001s,go Mutex,24s+,linux下回去我也测试下。
PS有一点差异就是java用了while,循环了300次,三个线程就是900次,然后多了个if取余数,用chan只是300次,没有if和余数。
我另外又专门写个程序java while 900次,每一次都有取3的余数,一共耗时0.092s,就上面的数据去掉这个,仍然有100倍的差距。java的csp库我没有用过,不知道会不会有明显提升。
因为刚学go,代码写的不一定是好的用法,熟悉go的童鞋请不吝指教下,十分感谢。
等级: 初级会员
发表时间:&&
Go使用sync.Mutex性能低的解决方案:
在m.Unlock()后面添加runtime.Gosched(),主动让出CPU
package main
import "fmt"
import "sync"
import "time"
import "runtime"
var m *sync.Mutex = new(sync.Mutex)
var i = 0
var max = 300
func Print(content string, divNum int, wg *sync.WaitGroup){
if i % 3 == divNum {
fmt.Println(content)
m.Unlock()
&&&&&&&&&&&&&& runtime.Gosched()
wg.Done()
}
func main(){
var wg sync.WaitGroup
start := time.Now()
go Print("A", 0, &wg)
go Print("B", 1, &wg)
go Print("C", 2, &wg)
duration := time.Since(start)
fmt.Println(duration.Seconds())
}
请登录后投票
来自: 深圳
发表时间:&&
谢谢,试了下,果然如此。3ks
请登录后投票
跳转论坛:移动开发技术
Web前端技术
Java企业应用
编程语言技术1586人阅读
GoLang(28)
本文介绍go利用管道如何进行并发计算,需要注意go的管道是双向的,而UNIX管道是单向的。
PS: 在测试时自己建立了一个后缀为_test.go的文件,build后会提示如下错误:
一句话解释:在go中文件名后缀为_test.go的都是单元测试文件。
具体可参考:
本例参考《go语言程序设计》第七章的一个例子,并添加了一些注释。
package main
&path/filepath&
func main() {
// Use all the machine's cores
runtime.GOMAXPROCS(runtime.NumCPU())
log.SetFlags(0)
// 处理命令行参数
algorithm, minSize, maxSize, suffixes, files := handleCommandLine()
// 开始计算操作
if algorithm == 1 {
// 算法1是并行计算, 通过创建各个的goroutine
// step1: 先通过source函数处理文件列表, 并把处理结果返回到管道里
// step2: 将符合后缀的文件放到管道里
// step3: 将符合大小的文件放到管道里
// step4: 从管道获取结果数据
sink(filterSize(minSize, maxSize, filterSuffixes(suffixes, source(files))))
// 算法2是串行计算
channel1 := source(files)
channel2 := filterSuffixes(suffixes, channel1)
channel3 := filterSize(minSize, maxSize, channel2)
sink(channel3)
// 命令行参数解析操作
func handleCommandLine() (algorithm int, minSize, maxSize int64,
suffixes, files []string) {
// 将命令行参数绑定到对应的变量中
// algorithm默认为1
flag.IntVar(&algorithm, &algorithm&, 1, &1 or 2&)
// minSize和maxSize默认为-1, 表示没有限制
flag.Int64Var(&minSize, &min&, -1,
&minimum file size (-1 means no minimum)&)
flag.Int64Var(&maxSize, &max&, -1,
&maximum file size (-1 means no maximum)&)
// suffixes后缀列表默认为空
var suffixesOpt *string = flag.String(&suffixes&, &&,
&comma-separated list of file suffixes&)
// 命令行预处理
flag.Parse()
if algorithm != 1 && algorithm != 2 {
algorithm = 1
if minSize & maxSize && maxSize != -1 {
// Fatalln is equivalent to Println() followed by a call to os.Exit(1)
log.Fatalln(&minimum size must be & maximum size&)
// 将后缀列表用逗号分隔, 返回suffixes后缀切片
suffixes = []string{}
if *suffixesOpt != && {
suffixes = strings.Split(*suffixesOpt, &,&)
// Args returns the non-flag command-line arguments
// 认为非命令选项的参数全为文件参数
files = flag.Args()
return algorithm, minSize, maxSize, suffixes, files
// 创建管道, 处理文件列表并把结果返回到管道里
func source(files []string) &-chan string {
out := make(chan string, 1000)
go func() {
for _, filename := range files {
out &- filename
close(out)
return out
// 将符合后缀的文件放到管道里
// 根据后缀切片处理管道里的文件, 同样再把结果返回到管道里
// make the buffer the same size as for files to maximize throughput
func filterSuffixes(suffixes []string, in &-chan string) &-chan string {
out := make(chan string, cap(in))
go func() {
for filename := range in {
// 没有限制后缀的话, 则直接将文件塞到管道里
if len(suffixes) == 0 {
out &- filename
// 获取文件列表的后缀, 且全部转换为小写
// Ext returns the file name extension used by path. The extension is the suffix beginning at the final dot in the f it is empty if there is no dot
ext := strings.ToLower(filepath.Ext(filename))
for _, suffix := range suffixes {
if ext == suffix {
out &- filename
close(out)
return out
// 将符合文件大小的文件放到管道里
// make the buffer the same size as for files to maximize throughput
func filterSize(minimum, maximum int64, in &-chan string) &-chan string {
out := make(chan string, cap(in))
go func() {
for filename := range in {
// 对文件大小没有限制, 直接将文件塞到管道里
if minimum == -1 && maximum == -1 {
out &- filename // don't do a stat call it not needed
// 使用操作系统的接口获取文件大小等信息
// Stat returns a FileInfo describing the named file. If there is an error, it will be of type *PathError
type FileInfo interface {
Name() string
// base name of the file
Size() int64
// length in byt system-dependent for others
Mode() FileMode
// file mode bits
ModTime() time.Time // modification time
IsDir() bool
// abbreviation for Mode().IsDir()
Sys() interface{}
// underlying data source (can return nil)
finfo, err := os.Stat(filename)
if err != nil {
continue // ignore files we can't process
size := finfo.Size()
if (minimum == -1 || minimum & -1 && minimum &= size) &&
(maximum == -1 || maximum & -1 && maximum &= size) {
out &- filename
close(out)
return out
// 从管道获取结果数据
func sink(in &-chan string) {
for filename := range in {
fmt.Println(filename)
mba:go gerryyang$ ./filter_t -min 1 -suffixes &.cpp& ../c++11/range_for.cpp ../c++11/test ../c++11/test.cpp routines.go
../c++11/range_for.cpp
../c++11/test.cpp
mba:go gerryyang$ ./filter_t -min 1 -max -2 -suffixes &.cpp& ../c++11/range_for.cpp ../c++11/test ../c++11/test.cpp routines.go jjjj
minimum size must be & maximum size
在网上发现一个go的学习站点,有空可以逛下:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1360467次
积分:16716
积分:16716
排名:第484名
原创:432篇
译文:10篇
评论:227条
文章:14篇
阅读:86020
(2)(1)(1)(1)(2)(2)(7)(7)(1)(2)(2)(2)(5)(1)(1)(2)(1)(1)(1)(3)(4)(6)(11)(8)(4)(4)(3)(3)(3)(2)(4)(2)(5)(2)(9)(2)(9)(2)(1)(1)(3)(3)(3)(1)(1)(4)(5)(3)(6)(9)(2)(1)(2)(2)(1)(2)(5)(5)(2)(3)(6)(4)(3)(1)(1)(7)(10)(20)(20)(15)(10)(7)(8)(20)(4)(3)(18)(18)(6)(20)(18)(7)(4)(18)(14)(11)

我要回帖

更多关于 京东理财金转到零用钱 的文章

 

随机推荐