es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo retrasar adecuadamente la ejecución entre un grupo de trabajadores.

Buen día,

Estoy tratando de implementar el retraso correcto entre la ejecución de los trabajadores. Por ejemplo, es necesario que los trabajadores completen 30 tareas y luego se duerman durante 5 segundos. ¿Cómo puedo rastrear en el código que se han completado exactamente 30 tareas y solo después de eso dormir durante 5 segundos?

A continuación se muestra el código que crea un grupo de 30 trabajadores, quienes a su vez realizan tareas de 30 piezas a la vez de manera desordenada, aquí está el código:

“`package main

import (
"fmt"
"math/rand"
"sync"
"time"
)

type Job struct {
id int
randomno int
}

type Result struct {
job Job
sumofdigits int
}

var jobs = make(chan Job, 10)
var results = make(chan Result, 10)

func digits(number int) int {
sum := 0
no := number
for no != 0 {
digit := no % 10
sum += digit
no /= 10
}
time.Sleep(2 * time.Second)
return sum
}

func worker(wg *sync.WaitGroup) {
for job := range jobs {
output := Result{job, digits(job.randomno)}
results <- output
}
wg.Done()
}

func createWorkerPool(noOfWorkers int) {
var wg sync.WaitGroup
for i := 0; i < noOfWorkers; i++ {
wg.Add(1)
go worker(&wg)
}

<pre><code>wg.Wait()
close(results)
</code></pre>

}

func allocate(noOfJobs int) {
for i := 0; i < noOfJobs; i++ {
if i != 0 && i%30 == 0 {
fmt.Printf("ESPERANDO 5 segundos…")
time.Sleep(10 * time.Second)
}

<pre><code> randomno := rand.Intn(999)
job := Job{i, randomno}
jobs <- job
}
close(jobs)
</code></pre>

}

func result(done chan bool) {
for result := range results {
fmt.Printf("ID de trabajo %d, número aleatorio de entrada %d, suma de los dígitos %d\n", result.job.id, result.job.randomno, result.sumofdigits)
}
done <- true
}

func main() {
startTime := time.Now()
noOfJobs := 100
go allocate(noOfJobs)
done := make(chan bool)
go result(done)
noOfWorkers := 30
createWorkerPool(noOfWorkers)
<-done
endTime := time.Now()
diff := endTime.Sub(startTime)
fmt.Println("tiempo total transcurrido", diff.Seconds(), "segundos")
}
“`

Juega: https://go.dev/play/p/lehl7hoo-kp

No está claro cómo asegurarse de que se completen 30 tareas y dónde insertar el retraso. Agradeceré cualquier ayuda.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para hacer un seguimiento de que exactamente se han completado 30 tareas y solo después de eso dormir durante 5 segundos, puedes hacer uso de un contador.

    Primero, inicializa un contador en 0 fuera de la función “allocate”.

    Luego, dentro de la función “worker”, incrementa el contador cada vez que se completa una tarea utilizando “atomic.AddInt32” del paquete “sync/atomic” para garantizar la seguridad de las hebras.

    Una vez que el contador llega a 30, la función “allocate” puede dormir durante 5 segundos antes de continuar asignando más trabajos.

    Aquí está el código modificado:

    package main
    
    import (
        "fmt"
        "math/rand"
        "sync"
        "sync/atomic" // importar el paquete sync/atomic
        "time"
    )
    
    type Job struct {
        id       int
        randomno int
    }
    type Result struct {
        job         Job
        sumofdigits int
    }
    
    var jobs = make(chan Job, 10)
    var results = make(chan Result, 10)
    var counter int32 // inicializar el contador en 0
    
    func digits(number int) int {
        sum := 0
        no := number
        for no != 0 {
            digit := no % 10
            sum += digit
            no /= 10
        }
        time.Sleep(2 * time.Second)
        return sum
    }
    
    func worker(wg *sync.WaitGroup) {
        for job := range jobs {
            output := Result{job, digits(job.randomno)}
            results <- output
            // incrementar el contador cada vez que se completa una tarea
            atomic.AddInt32(&counter, 1)
        }
        wg.Done()
    }
    
    func createWorkerPool(noOfWorkers int) {
        var wg sync.WaitGroup
        for i := 0; i < noOfWorkers; i++ {
            wg.Add(1)
            go worker(&wg)
        }
    
        wg.Wait()
        close(results)
    }
    
    func allocate(noOfJobs int) {
        for i := 0; i < noOfJobs; i++ {
            // verificar si se han completado 30 tareas
            if atomic.LoadInt32(&counter) != 0 && atomic.LoadInt32(&counter)%30 == 0 {
                fmt.Printf("SLEEPAGE 5 sec...")
                time.Sleep(5 * time.Second)
            }
            randomno := rand.Intn(999)
            job := Job{i, randomno}
            jobs <- job
        }
        close(jobs)
    }
    
    func result(done chan bool) {
        for result := range results {
            fmt.Printf("ID de trabajo %d, número aleatorio de entrada %d, suma de dígitos %d\n", result.job.id, result.job.randomno, result.sumofdigits)
        }
        done <- true
    }
    
    func main() {
        startTime := time.Now()
        noOfJobs := 100
        go allocate(noOfJobs)
        done := make(chan bool)
        go result(done)
        noOfWorkers := 30
        createWorkerPool(noOfWorkers)
        <-done
        endTime := time.Now()
        diff := endTime.Sub(startTime)
        fmt.Println("tiempo total transcurrido", diff.Seconds(), "segundos")
    }
    

    Puedes ver el ejemplo funcional aquí: https://go.dev/play/p/TjhTQJGL9X9.

Comments are closed.