Racket/Multitråd
Från Täpp-Anders
Hoppa till navigeringHoppa till sök
#lang racket
;;;;;
;; Multitrådad demo
;; Täpp-Anders Sikvall, anders@sikvall.se, 2006-04-04
;; Racketkurs.
;; Simulerar tidsödande arbete genom att pausa tråden en slumpmässig tid
(define (random-sleep min-sec max-sec)
(sleep (+ min-sec (* (random) (- max-sec min-sec)))))
;; En arbetare körs i en egen tråd och lyssnar på work-channel
(define (start-worker id work-channel result-channel)
(thread
(λ ()
(let loop ()
;; Vänta på att få ett meddelande från arbetskön
(match (channel-get work-channel)
;; Om meddelandet är 'done', avsluta loopen och därmed tråden
['done
(printf "Arbetare ~a: Avslutar.\n" id)]
;; Om meddelandet är ett tal, utför beräkningen
[n
(printf "Arbetare ~a: Bearbetar värde ~a...\n" id n)
(random-sleep 0.1 0.4)
;; Skicka tillbaka resultatet.
;; OBS: Detta blockerar arbetaren tills huvudtråden läser från result-channel.
(channel-put result-channel (list id (* n n)))
(loop)])))))
;; --- Huvudprogram ---
(define (main)
(define num-workers 4)
(define num-tasks 10)
;; Skapa kanaler för kommunikation
;; Dessa är synkrona (blockerande) i Racket
(define work-channel (make-channel))
(define result-channel (make-channel))
(printf "System: Startar ~a arbetstrådar.\n" num-workers)
;; Starta arbetartrådarna och spara deras referenser i en lista
(define workers
(for/list ([i (in-range num-workers)])
(start-worker i work-channel result-channel)))
;; 1. Skicka uppgifter till arbetskön.
;; Vi gör detta i en separat tråd för att säkerställa att huvudtråden
;; kan börja tömma resultat-kanalen omedelbart.
(thread
(λ ()
(for ([task (in-range 1 (add1 num-tasks))])
(channel-put work-channel task))
;; Skicka en 'done'-signal per arbetare för att stänga ner dem snyggt
(for ([_ (in-range num-workers)])
(channel-put work-channel 'done))))
;; Samla in resultaten.
(printf "System: Samlar in resultat.\n")
(for ([_ (in-range num-tasks)])
(match (channel-get result-channel)
[(list id result)
(printf "Resultat: Arbetare ~a levererade ~a\n" id result)]))
;; Vänta på att trådarna faktiskt har stängt ner.
(printf "System: Väntar på att trådar stängs ner...\n")
(for-each thread-wait workers)
(printf "System: Programmet är klart.\n"))
;; Kör programmet
(main)