居眠り床屋を再度

import threading
import random
from time import sleep

class Seats(object):
  def __init__(self):
    self.queue = []

  def size(self):
    return len(self.queue)

  def push(self, id):
    self.queue.append(id)
  
  def pop(self):
    result, self.queue = self.queue[0], self.queue[1::]
    return result

  def peek(self):
    return self.queue[0]

class BarberThread(threading.Thread):
  def __init__(self, e, q):
    threading.Thread.__init__(self)
    self.e = e
    self.q = q
    self.officeHours = True

  def close(self):
    self.officeHours = False

  def run(self):
    while self.officeHours:
      if self.q.size() == 0:
        log('sleep start...')
        self.e.wait(15)
        if self.officeHours:
          log('awake!')

      if self.q.size() > 0:
        customer = self.q.peek()
        log('cut start %s' % (customer))
        sleep(random.randint(100, 400) / 1000.0)
        self.q.pop()
        log('cut end %s' % (customer))

class CustomerThread(threading.Thread):
  def __init__(self, id, e, q):
    threading.Thread.__init__(self)
    self.id = id
    self.e = e
    self.q = q

  def run(self):
    log('enter %s' % (self.id))
    if self.q.size() >= 3:
      log('full, out %d' % (self.id))
    else:
      self.q.push(self.id)
      self.e.set()
      self.e.clear()

def log(msg):
  print("[%s] %s" % (threading.currentThread().getName(), msg))

def main():
  random.seed()
  q = Seats()
  e = threading.Event()
  b = BarberThread(e, q)

  log('open!!!!!')
  b.start()

  for i in xrange(16):
    c = CustomerThread(i+1, e, q)
    if i == 9:
      sleep(1200 / 1000.0)
    else:
      sleep(random.randint(0, 200) / 1000.0)
    c.start()

  sleep(3)
  log('close!!!!!')
  b.close()
  e.set()
  e.clear()

if __name__ == '__main__':
  main()

"""
[MainThread] open!!!!!
[Thread-1] sleep start...
[Thread-2] enter 1
[Thread-1] awake!
[Thread-1] cut start 1
[Thread-1] cut end 1
[Thread-1] sleep start...
[Thread-3] enter 2
[Thread-1] awake!
[Thread-1] cut start 2
[Thread-4] enter 3
[Thread-5] enter 4
[Thread-1] cut end 2
[Thread-1] cut start 3
[Thread-6] enter 5
[Thread-7] enter 6
[Thread-7] full, out 6
[Thread-8] enter 7
[Thread-8] full, out 7
[Thread-1] cut end 3
[Thread-1] cut start 4
[Thread-9] enter 8
[Thread-10] enter 9
[Thread-10] full, out 9
[Thread-1] cut end 4
[Thread-1] cut start 5
[Thread-1] cut end 5
[Thread-1] cut start 8
[Thread-1] cut end 8
[Thread-1] sleep start...
[Thread-11] enter 10
[Thread-1] awake!
[Thread-1] cut start 10
[Thread-12] enter 11
[Thread-13] enter 12
[Thread-14] enter 13
[Thread-14] full, out 13
[Thread-1] cut end 10
[Thread-1] cut start 11
[Thread-15] enter 14
[Thread-1] cut end 11
[Thread-1] cut start 12
[Thread-16] enter 15
[Thread-17] enter 16
[Thread-17] full, out 16
[Thread-1] cut end 12
[Thread-1] cut start 14
[Thread-1] cut end 14
[Thread-1] cut start 15
[Thread-1] cut end 15
[Thread-1] sleep start...
[MainThread] close!!!!!
"""

Threadのドキュメントを読んだ他は、勘だけで書いてみたけど、合ってるんだか。
Threadの終了のさせ方がわからなかったので外部からフラグ操作するようにした。
super()が欲しい。


文言が2バイト文字じゃないのは、sjisで書いてたから。