首页 \ 问答 \ 何时在netty中使用Unpooled(when to use Unpooled in netty)

何时在netty中使用Unpooled(when to use Unpooled in netty)

我想知道何时在Netty中使用Unpooled 。 一些示例显示在Unpooled.wrappedBuffer包装了byte [],并且一些示例仅显示

ctx.writeAndFlush(bytes); // where bytes is just byte[]

是否有关于何时使用Unpooled的指南?


I'm trying to figure out when to use Unpooled in Netty. Some examples show wrapped the byte[] in Unpooled.wrappedBuffer, and some examples show just

ctx.writeAndFlush(bytes); // where bytes is just byte[]

Is there a guideline on when to use Unpooled?


原文:https://stackoverflow.com/questions/45291211
更新时间:2022-10-06 10:10

最满意答案

这样写的代码会产生一个死锁。 但是,渠道不一定要关闭。 有多种方法可以解决此问题。

例如,你可以通过以下方法替换for / select循环:

n := len(requests)
for r := range ch {
    processResponse(r)
    n--
    if n == 0 {
        break
    }
}

这里我们假设潜在的超时在每个goroutine中进行管理。

另一个真正依赖关闭频道的解决方案可以写成如下:

func asyncHttpGets(requests []HttpRequest) {

    ch := make(chan *HttpResponse)
    var wg sync.WaitGroup
    for _, request := range requests {
        wg.Add(1)
        go func(r HttpRequest) {
            defer wg.Done()
            resp, err := http.Get(r.url)
            ch <- &HttpResponse{r, resp, err}
        }(request)
    }

    go func() {
        wg.Wait()
        close(ch)
    }()
    for r := range ch {
        processResponse(r)
    }
}

请注意,比较初始代码,请求变量不是从goroutine访问的,而是作为参数传递的。 因此,通过通道发布的输出数据结构是一致的。 这是初始代码中的一个问题。 有关此特定主题的更多信息,请访问: https//github.com/golang/go/wiki/CommonMistakes

另一种解决方案是使用原子计数器计数goroutine中的响应,并在计数器达到极限时明确关闭通道。 但是处理同步/原子常常容易出错,所以在这里可能不是个好主意。

最后,有时您需要获得更多控制权才能正确管理超时,错误等... Tomb包可以帮助您以安全的方式管理goroutines的生命周期。

请参阅https://github.com/go-tomb/tomb/tree/v2


The code, written like this, will produce a deadlock. But, the channel does not have necessarily to be closed. There are multiple ways to solve this issue.

For instance, you could replace the for/select loop by:

n := len(requests)
for r := range ch {
    processResponse(r)
    n--
    if n == 0 {
        break
    }
}

Here we assume that the potential timeouts are managed in each goroutine.

Another solution, which really relies on closing the channel could be written as follows:

func asyncHttpGets(requests []HttpRequest) {

    ch := make(chan *HttpResponse)
    var wg sync.WaitGroup
    for _, request := range requests {
        wg.Add(1)
        go func(r HttpRequest) {
            defer wg.Done()
            resp, err := http.Get(r.url)
            ch <- &HttpResponse{r, resp, err}
        }(request)
    }

    go func() {
        wg.Wait()
        close(ch)
    }()
    for r := range ch {
        processResponse(r)
    }
}

Note that compared the initial code, the request variable is not accessed from the goroutine, but passed as a parameter. The output data structure posted via the channel is therefore consistent. This was an issue in the initial code. See more information about this specific topic at: https://github.com/golang/go/wiki/CommonMistakes

Yet another solution would be to count the responses in the goroutines using an atomic counter, and explicitly close the channel when the counter reaches the limit. But dealing with sync/atomic is often error-prone, so it is probably not a good idea here.

Finally, sometimes you need to get more control in order to properly manage timeouts, errors, etc ... The tomb package can help you to manage the lifecycle of the goroutines in a safe way.

See https://github.com/go-tomb/tomb/tree/v2

相关问答

更多
  • 默认情况下,发送和接收阻塞,直到另一侧准备就绪。 确切地说:因为没有去程序正在等待接收,所以发送被阻塞,并且程序死锁。 发送操作不会被跳过,因为没有人正在等待接收。 如果你想做一个非阻塞发送,你可以在一个带默认情况的select语句中使用send操作符: select { case c <- 17: default: } By default, sends and receives block until the other side is ready. Exactly: since no go rout ...
  • 显然,互联网上没有人想出(或需要弄清楚)如何做到这一点,所以我只是盯着API概述足够长的时间,直到它来到我身边。 当您创建“socket”变量时,秘密在API的Javascript部分。 Javascript API声明套接字var还具有“close()”函数。 考虑到我用Java编写了我的实现,这对我来说有点棘手,因为我不得不抹去我对JSNI的了解,而socket var仅在我的“join”调用期间存在。 为了解决这个问题,我在套接字变量中创建了一个全局变量,在本例中称为“globalSocket”,然后 ...
  • 我不确定你想要实现的目标。 但是您的示例代码可以保证在select语句中阻塞。 select的default情况用于在通道上的特定读取或写入不成功时提供回退。 这意味着在您的代码中,始终执行默认情况。 在选择开始之前,没有任何值写入通道,因此case语句永远不会运行。 default情况下的代码永远不会成功并无限期阻塞,因为通道中没有空间来存储值,而其他任何人都没有从中读取任何其他goroutine。 解决您当前问题的简单方法是: stopSvr=make(chan bool, 1) // 1 slot b ...
  • 没有结果是不一样的: 在许多情况下(例如,不同的CPU负载,它是非确定性和系统依赖的行为),您的主要参数会在您received job之前退出,所以您不能保证all jobs received ,例如只是添加 time.Sleep(500) 之前 fmt.Println("received job", j) 看看这个,在The Go Playground上试试看: // _Closing_ a channel indicates that no more values // will be sent o ...
  • 这是因为主要的goroutine卡in in <- true 另一个goroutine卡住out out <- 1 如果你写出一个case它应该工作: for { select { case <-in: fmt.Println("Close") close(out) return case out <- 1: fmt.Println("Out") break } } This is beca ...
  • 这样写的代码会产生一个死锁。 但是,渠道不一定要关闭。 有多种方法可以解决此问题。 例如,你可以通过以下方法替换for / select循环: n := len(requests) for r := range ch { processResponse(r) n-- if n == 0 { break } } 这里我们假设潜在的超时在每个goroutine中进行管理。 另一个真正依赖关闭频道的解决方案可以写成如下: func asyncHttpGets(re ...
  • 通常的做法是通过超时提供通道读取和写入。 这是一种安全措施,可确保在给定的时间间隔过后,goroutine停止阻塞。 一个用例就是启动N个例程以在各种http客户端上执行异步搜索。 你会想要尽可能多地等待结果,但你不想永远等待。 这些http获取程序将执行查询并将结果发送给您,前提是它们可以在设置超时内完成任务。 这是该原则的简单版本。 你可以在Go游乐场上运行它。 这里唯一的区别是goroutine正在从我们的队列通道读取,而不是向我们发送数据的那个。 但原则是相同的。 package main imp ...
  • 在调用wg.Wait()之前,对wg.Wait()的调用不会返回。 在addStuff() ,当没有其他goroutine来消耗这些值时,你addStuff()值写入通道。 由于通道是无缓冲的,因此对channel <- val的第一次调用将永远阻塞,从而导致死锁。 此外, addStuff()的通道仍为零,因为您在main中创建了一个新的变量绑定,而不是分配给包级变量。 写入nil通道会永久阻塞: channel := make(chan int) //doesn't affect the package ...
  • 延迟函数未执行的原因是应用程序到达main函数的末尾,导致整个程序终止而不等待goroutine。 Go规范说: 当函数main返回时,程序退出。 它不等待其他(非主要)goroutines完成。 由于你的recieveCakeAndPack仍在等待频道关闭(从未发生),它将永远不会在程序终止之前推迟。 编辑 另一方面 - 将延迟语句最后放在函数中是没有意义的。 而是将它们直接放在要延迟的语句之后,例如: fmt.Println("Entering function") defer fmt.Println( ...
  • 对我来说,它看起来并不像你正在从你的频道中读取,并且因为它是一个同步频道(你从未在其上声明长度),如果它收到一个值,它将阻止。 所以你需要通过value <- c读取你的c ,否则你的获取函数只会挂在c <- *e 这导致你的sync.WaitGroup从不wg.Done()从不递减计数器,这永远不会导致wg.Wait()停止阻塞,这导致你的close(c)永远不会被调用 To me it doesn't look like you're reading from your channel, and bec ...

相关文章

更多

最新问答

更多
  • python的访问器方法有哪些
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。
  • 响应navi重叠h1和nav上的h1链接不起作用(Responsive navi overlaps h1 and navi links on h1 isn't working)
  • 在C中读取文件:“r”和“a +”标志的不同行为(Reading a File in C: different behavior for “r” and “a+” flags)
  • NFC提供什么样的带宽?(What Kind of Bandwidth does NFC Provide?)
  • 元素上的盒子阴影行为(box-shadow behaviour on elements)
  • Laravel检查是否存在记录(Laravel Checking If a Record Exists)
  • 设置base64图像的大小javascript - angularjs(set size of a base64 image javascript - angularjs)
  • 想学Linux 运维 深圳有哪个培训机构好一点
  • 为什么有时不需要在lambda中捕获一个常量变量?(Why is a const variable sometimes not required to be captured in a lambda?)
  • 在Framework 3.5中使用服务器标签<%=%>设置Visible属性(Set Visible property with server tag <%= %> in Framework 3.5)
  • AdoNetAppender中的log4net连接类型无效(log4net connection type invalid in AdoNetAppender)
  • 错误:发送后无法设置标题。(Error: Can't set headers after they are sent. authentication system)
  • 等待EC2实例重启(Wait for an EC2 instance to reboot)
  • 如何在红宝石中使用正则表达式?(How to do this in regex in ruby?)
  • 使用鼠标在OpenGL GLUT中绘制多边形(Draw a polygon in OpenGL GLUT with mouse)
  • 江民杀毒软件的KSysnon.sys模块是什么东西?
  • 处理器在传递到add_xpath()或add_value()时调用了什么顺序?(What order are processors called when passed into add_xpath() or add_value()?)
  • sp_updatestats是否导致SQL Server 2005中无法访问表?(Does sp_updatestats cause tables to be inaccessible in SQL Server 2005?)
  • 如何创建一个可以与持续运行的服务交互的CLI,类似于MySQL的shell?(How to create a CLI that can interact with a continuously running service, similar to MySQL's shell?)
  • AESGCM解密失败的MAC(AESGCM decryption failing with MAC)
  • SQL查询,其中字段不包含$ x(SQL Query Where Field DOES NOT Contain $x)
  • PerSession与PerCall(PerSession vs. PerCall)
  • C#:有两个构造函数的对象:如何限制哪些属性设置在一起?(C#: Object having two constructors: how to limit which properties are set together?)
  • 平衡一个精灵(Balancing a sprite)
  • n2cms Asp.net在“文件”菜单上给出错误(文件管理器)(n2cms Asp.net give error on Files menu (File Manager))
  • Zurb Foundation 4 - 嵌套网格对齐问题(Zurb Foundation 4 - Nested grid alignment issues)
  • 湖北京山哪里有修平板计算机的