首页 \ 问答 \ 何时在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 ...

相关文章

更多

最新问答

更多
  • 在ios 7中的UITableView部分周围绘制边界线(draw borderline around UITableView section in ios 7)
  • Java中的不可变类(Immutable class in Java)
  • 寻求多次出现的表达式(Seeking for more than one occurrence of an expression)
  • linux只知道文件名,不知道在哪个目录,怎么找到文件所在目录
  • Actionscript:检查字符串是否包含域或子域(Actionscript: check if string contains domain or subdomain)
  • 懒惰地初始化AutoMapper(Lazily initializing AutoMapper)
  • 使用hasclass为多个div与一个按钮问题(using hasclass for multiple divs with one button Problems)
  • Windows Phone 7:检查资源是否存在(Windows Phone 7: Check If Resource Exists)
  • EXCEL VBA 基础教程下载
  • RoR - 邮件中的动态主体(部分)(RoR - Dynamic body (part) in mailer)
  • 无法在Google Script中返回2D数组?(Can not return 2D Array in Google Script?)
  • JAVA环境变量的设置和对path , classpth ,java_home设置作用和目的?
  • mysql 关于分组查询、时间条件查询
  • 如何使用PowerShell匹配运算符(How to use the PowerShell match operator)
  • Effective C ++,第三版:重载const函数(Effective C++, Third edition: Overloading const function)
  • 如何用DELPHI动态建立MYSQL的数据库和表? 请示出源代码。谢谢!
  • 带有简单redis应用程序的Node.js抛出“未处理的错误”(Node.js with simple redis application throwing 'unhandled error')
  • 使用前端框架带来哪些好处,相对于使用jquery
  • Ruby将字符串($ 100.99)转换为float或BigDecimal(Ruby convert string ($100.99) to float or BigDecimal)
  • 高考完可以去做些什么?注意什么?
  • 如何声明放在main之后的类模板?(How do I declare a class template that is placed after the main?)
  • 如何使用XSLT基于兄弟姐妹对元素进行分组(How to group elements based on their siblings using XSLT)
  • 在wordpress中的所有页面的标志(Logo in all pages in wordpress)
  • R:使用rollapply对列组进行求和的问题(R: Problems using rollapply to sum groups of columns)
  • Allauth不会保存其他字段(Allauth will not save additional fields)
  • python中使用sys模块中sys.exit()好像不能退出?
  • 将Int拆分为3个字节并返回C语言(Splitting an Int to 3 bytes and back in C)
  • 在SD / MMC中启用DDR会导致问题吗?(Enabling DDR in SD/MMC causes problems? CMD 11 gives a response but the voltage switch wont complete)
  • sed没有按预期工作,从字符串中间删除特殊字符(sed not working as expected, removing special character from middle of string)
  • 如何将字符串转换为Elixir中的函数(how to convert a string to a function in Elixir)