我最近一直在看Go的goroutines,并认为在Java中有类似的东西会很好.据我所知,并行化方法调用的常用方法是执行以下操作:
final String x = "somethingelse";
new Thread(new Runnable() {
public void run() {
x.matches("something");
}
}).start();
Run Code Online (Sandbox Code Playgroud)
那不是很优雅.有没有更好的方法呢?我在项目中需要这样的解决方案,所以我决定围绕异步方法调用实现自己的包装类.
我在J-Go发布了我的包装类.但我不知道这是不是一个好的解决方案.用法很简单:
SampleClass obj = ...
FutureResult<Integer> res = ...
Go go = new Go(obj);
go.callLater(res, "intReturningMethod", 10); //10 is a Integer method parameter
//... Do something else
//...
System.out.println("Result: "+res.get()); //Blocks until intReturningMethod returns
Run Code Online (Sandbox Code Playgroud)
或者更简洁:
Go.with(obj).callLater("myRandomMethod");
//... Go away
if (Go.lastResult().isReady()) //Blocks until myRandomMethod has ended
System.out.println("Method is finished!");
Run Code Online (Sandbox Code Playgroud)
在内部,我正在使用一个实现Runnable的类,并做一些Reflection工作来获取正确的方法对象并调用它.
我想对我的小型库以及在Java中进行这样的异步方法调用的主题有所了解.安全吗?有没有更简单的方法?
这个示例用法sync.WaitGroup
是否正确?它给出了预期的结果,但我不确定它wg.Add(4)
的位置和位置wg.Done()
.一次添加四个goroutines是否有意义wg.Add()
?
http://play.golang.org/p/ecvYHiie0P
package main
import (
"fmt"
"sync"
"time"
)
func dosomething(millisecs time.Duration, wg *sync.WaitGroup) {
duration := millisecs * time.Millisecond
time.Sleep(duration)
fmt.Println("Function in background, duration:", duration)
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(4)
go dosomething(200, &wg)
go dosomething(400, &wg)
go dosomething(150, &wg)
go dosomething(600, &wg)
wg.Wait()
fmt.Println("Done")
}
Run Code Online (Sandbox Code Playgroud)
结果(如预期):
Function in background, duration: 150ms
Function in background, duration: 200ms
Function in background, duration: 400ms
Function in background, duration: 600ms …
Run Code Online (Sandbox Code Playgroud) 此代码选择同一文件夹中的所有xml文件,与调用的可执行文件一样,并且异步地将处理应用于回调方法中的每个结果(在下面的示例中,只打印出文件的名称).
如何避免使用sleep方法来保持main方法退出?我有问题缠绕我的头围绕通道(我认为这是需要的,同步结果)所以任何帮助表示赞赏!
package main
import (
"fmt"
"io/ioutil"
"path"
"path/filepath"
"os"
"runtime"
"time"
)
func eachFile(extension string, callback func(file string)) {
exeDir := filepath.Dir(os.Args[0])
files, _ := ioutil.ReadDir(exeDir)
for _, f := range files {
fileName := f.Name()
if extension == path.Ext(fileName) {
go callback(fileName)
}
}
}
func main() {
maxProcs := runtime.NumCPU()
runtime.GOMAXPROCS(maxProcs)
eachFile(".xml", func(fileName string) {
// Custom logic goes in here
fmt.Println(fileName)
})
// This is what i want to get rid of
time.Sleep(100 * time.Millisecond) …
Run Code Online (Sandbox Code Playgroud) 我有一个调用方法的goroutine,并在通道上传递返回值:
ch := make(chan int, 100)
go func(){
for {
ch <- do_stuff()
}
}()
Run Code Online (Sandbox Code Playgroud)
我怎么停止这样的goroutine?
TL; TR:请转到最后一部分告诉我你将如何解决这个问题.
我今天早上开始使用Golang来自Python.我想从Go调用一个闭源可执行文件几次,带有一点并发性,使用不同的命令行参数.我生成的代码工作正常,但我想得到你的输入以改进它.由于我处于早期学习阶段,我还将解释我的工作流程.
为简单起见,这里假设这个"外部闭源程序"是zenity
一个Linux命令行工具,可以从命令行显示图形消息框.
所以,在Go中,我会这样:
package main
import "os/exec"
func main() {
cmd := exec.Command("zenity", "--info", "--text='Hello World'")
cmd.Run()
}
Run Code Online (Sandbox Code Playgroud)
这应该是正常的.注意,这.Run()
是一个功能等同于.Start()
后面跟着.Wait()
.这很棒,但如果我只想执行一次这个程序,整个编程的东西就不值得了.所以,让我们多次这样做.
现在我有了这个工作,我想用自定义命令行参数多次调用我的程序(这里只是i
为了简单起见).
package main
import (
"os/exec"
"strconv"
)
func main() {
NumEl := 8 // Number of times the external program is called
for i:=0; i<NumEl; i++ {
cmd := exec.Command("zenity", "--info", "--text='Hello from iteration n." + strconv.Itoa(i) + "'")
cmd.Run()
}
}
Run Code Online (Sandbox Code Playgroud)
好的,我们做到了!但我仍然看不到Go over …
我可以使用多少goroutines无痛?例如维基百科说,在Erlang中,可以创建2000万个进程,而不会降低性能.
更新:我刚刚调查了goroutines性能并得到了这样的结果:
我是golang的新手,所以请原谅这是一个非常基本的问题.下面的代码给出了编译错误,说'意外去':
x := go doSomething(arg)
func doSomething(arg int) int{
...
return my_int_value
}
Run Code Online (Sandbox Code Playgroud)
我知道,如果不正常调用函数,我可以获取返回值,而不使用goroutine.或者我可以使用频道等
我的问题是为什么不能从goroutine获取这样的返回值.
在调用系统调用时,其他goroutine如何继续执行?(当使用GOMAXPROCS = 1时)
据我所知,在调用系统调用时,线程会放弃控制,直到系统调用返回为止.Go如何在不使用block-on-syscall goroutine创建系统线程的情况下实现这种并发性?
从文档:
够程
它们被称为goroutines,因为现有的术语 - 线程,协同程序,进程等 - 传达了不准确的内涵.goroutine有一个简单的模型:它是一个与同一地址空间中的其他goroutine同时执行的函数.它是轻量级的,比堆栈空间的分配花费更多.并且堆栈开始很小,因此它们很便宜,并且通过根据需要分配(和释放)堆存储来增长.
Goroutines被多路复用到多个OS线程上,因此如果应该阻塞,例如在等待I/O时,其他线程继续运行.他们的设计隐藏了线程创建和管理的许多复杂性.
在Google I/O 2012演示文稿Go Concurrency Patterns中,Rob Pike提到几个goroutine可以存在于一个线程中.这是否意味着它们是作为协同程序实现的?如果没有,它们是如何实施的?欢迎链接到源代码.
我用Go编写了一个长期运行的服务器.Main触发了程序逻辑执行的几个goroutine.之后主要没有任何用处.一旦主要退出,程序将退出.我现在用来保持程序运行的方法只是对fmt.Scanln()的简单调用.我想知道别人如何保持主力退出.以下是一个基本的例子.这里可以使用哪些想法或最佳实践?
我考虑通过在所述频道上接收来创建一个频道并延迟主要的退出,但我认为如果我的所有goroutine在某些时候变得不活跃,那么这可能会有问题.
旁注:在我的服务器(不是示例)中,程序实际上并没有连接到shell,因此无论如何与控制台交互都没有意义.现在它可行,但我正在寻找"正确"的方式,假设有一个.
package main
import (
"fmt"
"time"
)
func main() {
go forever()
//Keep this goroutine from exiting
//so that the program doesn't end.
//This is the focus of my question.
fmt.Scanln()
}
func forever() {
for ; ; {
//An example goroutine that might run
//indefinitely. In actual implementation
//it might block on a chanel receive instead
//of time.Sleep for example.
fmt.Printf("%v+\n", time.Now())
time.Sleep(time.Second)
}
}
Run Code Online (Sandbox Code Playgroud) goroutine ×10
go ×9
concurrency ×3
asynchronous ×1
channels ×1
daemon ×1
java ×1
multitasking ×1