• golang 基于channel封装资源池(可用于封装redis、mq连接池)


    package pool
    import (
      "errors"
      "io"
      "sync"
      "time"
    )
     
    var (
      ErrInvalidConfig = errors.New("invalid pool config")
      ErrPoolClosed  = errors.New("pool closed")
    )
     
    type factory func() (io.Closer, error)
     
    type Pool interface {
      Acquire() (io.Closer, error) // 获取资源
      Release(io.Closer) error   // 释放资源
      Close(io.Closer) error    // 关闭资源
      Shutdown() error       // 关闭池
    }
     
    type GenericPool struct {
      sync.Mutex
      pool    chan io.Closer
      maxOpen   int // 池中最大资源数
      numOpen   int // 当前池中资源数
      minOpen   int // 池中最少资源数
      closed   bool // 池是否已关闭
      maxLifetime time.Duration
      factory   factory // 创建连接的方法
    }
     
    func NewGenericPool(minOpen, maxOpen int, maxLifetime time.Duration, factory factory) (*GenericPool, error) {
      if maxOpen <= 0 || minOpen > maxOpen {
        return nil, ErrInvalidConfig
      }
      p := &GenericPool{
        maxOpen:   maxOpen,
        minOpen:   minOpen,
        maxLifetime: maxLifetime,
        factory:   factory,
        pool:    make(chan io.Closer, maxOpen),
      }
     
      for i := 0; i < minOpen; i++ {
        closer, err := factory()
        if err != nil {
          continue
        }
        p.numOpen++
        p.pool <- closer
      }
      return p, nil
    }
     
    func (p *GenericPool) Acquire() (io.Closer, error) {
      if p.closed {
        return nil, ErrPoolClosed
      }
      for {
        closer, err := p.getOrCreate()
        if err != nil {
          return nil, err
        }
        // todo maxLifttime处理
        return closer, nil
      }
    }
     
    func (p *GenericPool) getOrCreate() (io.Closer, error) {
      select {
      case closer := <-p.pool:
        return closer, nil
      default:
      }
      p.Lock()
      if p.numOpen >= p.maxOpen {
        closer := <-p.pool
        p.Unlock()
        return closer, nil
      }
      // 新建连接
      closer, err := p.factory()
      if err != nil {
        p.Unlock()
        return nil, err
      }
      p.numOpen++
      p.Unlock()
      return closer, nil
    }
     
    // 释放单个资源到连接池
    func (p *GenericPool) Release(closer io.Closer) error {
      if p.closed {
        return ErrPoolClosed
      }
      p.Lock()
      p.pool <- closer
      p.Unlock()
      return nil
    }
     
    // 关闭单个资源
    func (p *GenericPool) Close(closer io.Closer) error {
      p.Lock()
      closer.Close()
      p.numOpen--
      p.Unlock()
      return nil
    }
     
    // 关闭连接池,释放所有资源
    func (p *GenericPool) Shutdown() error {
      if p.closed {
        return ErrPoolClosed
      }
      p.Lock()
      close(p.pool)
      for closer := range p.pool {
        closer.Close()
        p.numOpen--
      }
      p.closed = true
      p.Unlock()
      return nil
    }
    

      转:https://www.jb51.net/article/134302.htm

  • 相关阅读:
    vue 传参动态
    a href="tel" 拨打电话
    vue中rem的转换
    请求接口的封装
    http request 请求拦截器,有token值则配置上token值
    node溢出
    vue菜单切换
    vue的table切换
    vue页面初始化
    [论文笔记] Legacy Application Migration to the Cloud: Practicability and Methodology (SERVICES, 2012)
  • 原文地址:https://www.cnblogs.com/zipon/p/11315255.html
Copyright © 2020-2023  润新知