from atexit import register from random import randrange from threading import Thread, Lock, current_thread from time import ctime, sleep class CleanOutputSet(set): def __str__(self): return ', '.join(x for x in self) lock = Lock() loops = (randrange(2, 5) for x in range(randrange(3, 7))) remaining = CleanOutputSet() def loop(nsec): myname = current_thread().name lock.acquire() remaining.add(myname) print('{} started {}'.format(ctime(), myname)) lock.release() sleep(nsec) lock.acquire() remaining.remove(myname) print('{} Completed {} ({} secs)'.format(ctime(), myname, nsec)) print(' (remaining: {})'.format(remaining or None)) lock.release() def main(): print('starting at:', ctime()) for pause in loops: Thread(target=loop, args=(pause,)).start() @register def _atexit(): print('all done at:', ctime()) if __name__ == '__main__': main()
優化版使用上下文管理器:python
... def loop(nsec): myname = current_thread().name with lock: remaining.add(myname) print('{} started {}'.format(ctime(), myname)) sleep(nsec) with lock: remaining.remove(myname) print('{} Completed {} ({} secs)'.format(ctime(), myname, nsec)) print(' (remaining: {})'.format(remaining or None)) ...
from atexit import register from random import randrange from threading import BoundedSemaphore, Lock, Thread from time import ctime, sleep lock = Lock() MAX = 5 candytray = BoundedSemaphore(MAX) def refill(): with lock: print('Refilling candy...') try: candytray.release() except ValueError: print('full, skipping') else: print('ok') def buy(): with lock: print('Buying candy...') if candytray.acquire(False): print('OK') else: print('empty, skipping') def producer(loops): for x in range(loops): refill() sleep(randrange(3)) def consumer(loops): for x in range(loops): buy() sleep(randrange(3)) def _main(): print('starting at:{}'.format(ctime())) nloops = randrange(2, 6) print('THE CANDY MACHINE (full with {} bars)!'.format(MAX)) Thread(target=consumer, args=(randrange(nloops, nloops+MAX+2),)).start() Thread(target=producer, args=(randrange(nloops, nloops+MAX+2),)).start() @register def _atexit(): print('all DONE at:', ctime()) if __name__ == '__main__': _main()