How to measure execution time of this dinning philosopher program(python)?
Question: 
    from __future__ import print_function
    from threading import Semaphore, Lock, Thread
    from time import sleep
    from random import random
    import argparse
    from timeit import Timer
    
    (THINKING, EATING) = (0, 1) #philosopher states
    
    def left_fork(id):
        return id
    
    def right_fork(id):
        return (id+1) % NUM_PHILOSOPHER
    
    def right(id):
        return (id+1) % NUM_PHILOSOPHER
    
    def left(id):
        return (id+NUM_PHILOSOPHER-1) % NUM_PHILOSOPHER
    
    def get_fork(id):
        global mutex
        global tstate
        global sem
    
        mutex.acquire()
        tstate[id] = 'hungry'
        test(id)
        mutex.release()
        sem[id].acquire()
    
    def put_fork(id):
        global mutex
        global tstate
        global sem
    
        mutex.acquire()
        tstate[id] = 'thinking'
        test(right(id))
        test(left(id))
        mutex.release()
    
    def test(id):
        global tstate
        if tstate[id] == 'hungry' and tstate[left(id)] != 'eating' and tstate[right(id)] != 'eating':   
            tstate[id] = 'eating'
            sem[id].release()
    
    def philosophize_footman(id,meal):
        global forks
        global footman
        state = THINKING
        for i in range(meal):
            sleep(random())
            if(state == THINKING):
                msg = "Philosopher " + str(id) + " is thinking."
                #print(msg)
                footman.acquire()
                forks[right_fork(id)].acquire()
                forks[left_fork(id)].acquire()
                state = EATING
            else:
                msg = "Philosopher " + str(id) + " is eating."
                #print(msg)
                forks[right_fork(id)].release()
                forks[left_fork(id)].release()
                state = THINKING
                footman.release()
        print("Finish philosophize_footman")
    
    def philosophize_lefthand(id,meal):
        global forks
        state = THINKING
        for i in range(meal):
            sleep(random())
            if(state == THINKING):
                #define the left hand user.
                if(id == 3):
                    forks[left_fork(id)].acquire()
                    forks[right_fork(id)].acquire()
                    state = EATING
                else:
                    forks[right_fork(id)].acquire()
                    forks[left_fork(id)].acquire()
                    state = EATING
            else:
                if(id == 3):
                    forks[left_fork(id)].release()
                    forks[right_fork(id)].release()
                    state == THINKING   
                else:
                    forks[right_fork(id)].release()
                    forks[left_fork(id)].release()
                    state == THINKING
        print("Finish philosophize_lefthand")
    
    def philosophize_Tanenbaum(id,meal):
        for i in range(meal):
            get_fork(id)
            sleep(random())
            put_fork(id)
        print("Finish philosophize_Tanenbaum")
    
    def run_c(numP,numM):
        for m in range(numP):
            phil1 = Thread(target = philosophize_Tanenbaum,args = (m,numM))
            phil1.start()
    
    def run_a():
        global NUM_PHILOSOPHER
        global MEAL
        for i in range(NUM_PHILOSOPHER):
            phil = Thread(target = philosophize_footman, args = (i,MEAL))
            phil.start()
    
    def run_b(numP,numM):
        for n in range(numP):
            phil2 = Thread(target = philosophize_lefthand, args = (n,numM))
            phil2.start()
    
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser(description = 'Philosopher dining')
        parser.add_argument('--nphi','-n',
                            type = int,
                            default = 5,
                            help = 'add num_phi',
                            metavar = 'number of philosophers')
        parser.add_argument('--meal','-m',
                            type = int,
                            default = 100,
                            help = 'number of meals',
                            metavar = 'meal')
        args = parser.parse_args()
        NUM_PHILOSOPHER = args.nphi #define number fo philosophers
        MEAL = args.meal    #define number of meals
        forks = [Semaphore(1) for i in range(NUM_PHILOSOPHER)]  #defines forks
        sem = [Semaphore(0) for i in range(NUM_PHILOSOPHER)]    #semaphores
        footman = Semaphore(4) #limit the number of philosophers
        mutex = Semaphore(1)    #mutex
        tstate = ['thinking'] * NUM_PHILOSOPHER #T-states
    
        run_a()
    #   run_b(args.nphi,args.meal)
    #   run_c(args.nphi,args.meal)
        timer = Timer(run_a)
        print("Time:{:0.3f}s".format(timer. timeit(100)/100))
    

It is dinning philosopher problem solution by python. The code is listed
above. I want to measure the running time of function run_a(). But when using
timer, I found it doesn't work well. It prints the time result immediately(e.g
0.001s, but the code is still running.) So please help me with it! Thank you
very much.


Answer: You need to wait for the threads to finish; call
[`Thread.join()`](http://docs.python.org/2/library/threading.html#threading.Thread.join)
on each thread:

    
    
    def run_a():
        global NUM_PHILOSOPHER
        global MEAL
        threads = []
        for i in range(NUM_PHILOSOPHER):
            phil = Thread(target = philosophize_footman, args = (i,MEAL))
            phil.start()
            threads.append(phil)
    
        for t in threads:
            t.join()
    

The `Thread.join()` method blocks until the thread has completed, or you can
specify a timeout.

