2013-08-16 11 views
21

Desidero utilizzare Go per il download di fogli di calcolo dei prezzi delle azioni da Yahoo finance. Farò una richiesta http per ogni azione nella sua goroutine. Ho una lista di circa 2500 simboli, ma invece di fare 2500 richieste in parallelo, preferirei fare 250 alla volta. In Java vorrei creare un pool di thread e riutilizzare i thread come e quando vengono liberati. Stavo cercando di trovare qualcosa di simile, un pool di goroutine, se vuoi, ma non sono riuscito a trovare alcuna risorsa. Apprezzerei se qualcuno potesse dirmi come eseguire il compito a portata di mano o indicarmi risorse per lo stesso. Grazie!Come utilizzare un pool di goroutine

+0

Avete bisogno di queste goroutine in una piscina? Come in, li tratti come risorse che crei e riutilizzi. OPPURE, considerereste una soluzione più semplice in cui le goroutine sono usa e getta, ma controllate semplicemente quante di esse sono in esecuzione alla volta? – atedja

risposta

41

Il modo più semplice, suppongo, è di creare 250 goroutine e passare loro un canale che è possibile utilizzare per passare i collegamenti dalla goroutine principale a quelli secondari, ascoltando quel canale.

Quando tutti i collegamenti vengono passati alle goroutine, si chiude un canale e tutte le goroutine terminano il lavoro.

Per assicurarsi che la goroutine principale sia terminata prima che i bambini elaborino i dati, è possibile utilizzare sync.WaitGroup.

Ecco il codice per illustrare (non una versione finale di lavoro, ma indica il punto) che ho detto sopra:

func worker(linkChan chan string, wg *sync.WaitGroup) { 
    // Decreasing internal counter for wait-group as soon as goroutine finishes 
    defer wg.Done() 

    for url := range linkChan { 
    // Analyze value and do the job here 
    } 
} 

func main() { 
    lCh := make(chan string) 
    wg := new(sync.WaitGroup) 

    // Adding routines to workgroup and running then 
    for i := 0; i < 250; i++ { 
     wg.Add(1) 
     go worker(lCh, wg) 
    } 

    // Processing all links by spreading them to `free` goroutines 
    for _, link := range yourLinksSlice { 
     lCh <- link 
    } 

    // Closing channel (waiting in goroutines won't continue any more) 
    close(lCh) 

    // Waiting for all goroutines to finish (otherwise they die as main routine dies) 
    wg.Wait() 
} 
+3

Ecco un test su scala ridotta di questo codice in azione: http://play.golang.org/p/fruJiGBWjn – Druska

1

È possibile utilizzare la libreria implementazione pool di thread in Go da questo git repo

Here è il bel blog su come utilizzare i canali più pool di thread

Snippet dal blog

var (
MaxWorker = os.Getenv("MAX_WORKERS") 
MaxQueue = os.Getenv("MAX_QUEUE") 
) 

//Job represents the job to be run 
type Job struct { 
    Payload Payload 
} 

// A buffered channel that we can send work requests on. 
var JobQueue chan Job 

// Worker represents the worker that executes the job 
type Worker struct { 
    WorkerPool chan chan Job 
    JobChannel chan Job 
    quit  chan bool 
} 

func NewWorker(workerPool chan chan Job) Worker { 
    return Worker{ 
     WorkerPool: workerPool, 
     JobChannel: make(chan Job), 
     quit:  make(chan bool)} 
} 

// Start method starts the run loop for the worker, listening for a quit channel in 
// case we need to stop it 
func (w Worker) Start() { 
    go func() { 
     for { 
      // register the current worker into the worker queue. 
      w.WorkerPool <- w.JobChannel 

      select { 
      case job := <-w.JobChannel: 
       // we have received a work request. 
       if err := job.Payload.UploadToS3(); err != nil { 
        log.Errorf("Error uploading to S3: %s", err.Error()) 
       } 

      case <-w.quit: 
       // we have received a signal to stop 
       return 
      } 
     } 
    }() 
} 

// Stop signals the worker to stop listening for work requests. 
func (w Worker) Stop() { 
    go func() { 
     w.quit <- true 
    }() 
} 
Problemi correlati