75 lines
1.9 KiB
Python
75 lines
1.9 KiB
Python
from __future__ import with_statement # required for Python 2.5
|
|
import threading
|
|
import random
|
|
import time
|
|
|
|
terminate = threading.Event()
|
|
|
|
class Buckets:
|
|
def __init__(self, nbuckets):
|
|
self.nbuckets = nbuckets
|
|
self.values = [random.randrange(10) for i in range(nbuckets)]
|
|
self.lock = threading.Lock()
|
|
|
|
def __getitem__(self, i):
|
|
return self.values[i]
|
|
|
|
def transfer(self, src, dst, amount):
|
|
with self.lock:
|
|
amount = min(amount, self.values[src])
|
|
self.values[src] -= amount
|
|
self.values[dst] += amount
|
|
|
|
def snapshot(self):
|
|
# copy of the current state (synchronized)
|
|
with self.lock:
|
|
return self.values[:]
|
|
|
|
def randomize(buckets):
|
|
nbuckets = buckets.nbuckets
|
|
while not terminate.isSet():
|
|
src = random.randrange(nbuckets)
|
|
dst = random.randrange(nbuckets)
|
|
if dst!=src:
|
|
amount = random.randrange(20)
|
|
buckets.transfer(src, dst, amount)
|
|
|
|
def equalize(buckets):
|
|
nbuckets = buckets.nbuckets
|
|
while not terminate.isSet():
|
|
src = random.randrange(nbuckets)
|
|
dst = random.randrange(nbuckets)
|
|
if dst!=src:
|
|
amount = (buckets[src] - buckets[dst]) // 2
|
|
if amount>=0: buckets.transfer(src, dst, amount)
|
|
else: buckets.transfer(dst, src, -amount)
|
|
|
|
def print_state(buckets):
|
|
snapshot = buckets.snapshot()
|
|
for value in snapshot:
|
|
print '%2d' % value,
|
|
print '=', sum(snapshot)
|
|
|
|
# create 15 buckets
|
|
buckets = Buckets(15)
|
|
|
|
# the randomize thread
|
|
t1 = threading.Thread(target=randomize, args=[buckets])
|
|
t1.start()
|
|
|
|
# the equalize thread
|
|
t2 = threading.Thread(target=equalize, args=[buckets])
|
|
t2.start()
|
|
|
|
# main thread, display
|
|
try:
|
|
while True:
|
|
print_state(buckets)
|
|
time.sleep(1)
|
|
except KeyboardInterrupt: # ^C to finish
|
|
terminate.set()
|
|
|
|
# wait until all worker threads finish
|
|
t1.join()
|
|
t2.join()
|