最簡單的方法:使用target指定線程要執行的目標函數,再使用start()啓動。python
語法:編程
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
group恆爲None,保留將來使用。target爲要執行的函數名。name爲線程名,默認爲Thread-N,一般使用默認便可。但服務器端程序線程功能不一樣時,建議命名。安全
#!/usr/bin/env python3 # coding=utf-8 import threading def function(i): print ("function called by thread {0}".format(i)) threads = [] for i in range(5): t = threading.Thread(target=function , args=(i,)) threads.append(t) t.start() t.join()
執行結果:服務器
$ ./threading_define.py function called by thread 0 function called by thread 1 function called by thread 2 function called by thread 3 function called by thread 4
#!/usr/bin/env python3 # coding=utf-8 import threading import time def first_function(): print (threading.currentThread().getName()+ str(' is Starting \n')) time.sleep(3) print (threading.currentThread().getName()+ str( ' is Exiting \n')) def second_function(): print (threading.currentThread().getName()+ str(' is Starting \n')) time.sleep(2) print (threading.currentThread().getName()+ str( ' is Exiting \n')) def third_function(): print (threading.currentThread().getName()+\ str(' is Starting \n')) time.sleep(1) print (threading.currentThread().getName()+ str( ' is Exiting \n')) if __name__ == "__main__": t1 = threading.Thread(name='first_function', target=first_function) t2 = threading.Thread(name='second_function', target=second_function) t3 = threading.Thread(name='third_function',target=third_function) t1.start() t2.start() t3.start()
執行結果:數據結構
$ ./threading_name.py first_function is Starting second_function is Starting third_function is Starting third_function is Exiting second_function is Exiting first_function is Exiting
配合logging模塊一塊兒使用:app
#!/usr/bin/env python3 # coding=utf-8 import logging import threading import time logging.basicConfig( level=logging.DEBUG, format='[%(levelname)s] (%(threadName)-10s) %(message)s', ) def worker(): logging.debug('Starting') time.sleep(2) logging.debug('Exiting') def my_service(): logging.debug('Starting') time.sleep(3) logging.debug('Exiting') t = threading.Thread(name='my_service', target=my_service) w = threading.Thread(name='worker', target=worker) w2 = threading.Thread(target=worker) # use default name w.start() w2.start() t.start()
執行結果:dom
$ ./threading_names_log.py[DEBUG] (worker ) Starting [DEBUG] (Thread-1 ) Starting [DEBUG] (my_service) Starting [DEBUG] (worker ) Exiting [DEBUG] (Thread-1 ) Exiting [DEBUG] (my_service) Exiting
前面咱們的線程都是結構化編程的形式來建立。經過集成threading.Thread類也能夠建立線程。Thread類首先完成一些基本上初始化,而後調用它的run()。run()方法會會調用傳遞給構造函數的目標函數。函數
#!/usr/bin/env python3 # coding=utf-8 import logging import threading import time exitFlag = 0 class myThread (threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print ("Starting " + self.name) print_time(self.name, self.counter, 5) print ("Exiting " + self.name) def print_time(threadName, delay, counter): while counter: if exitFlag: thread.exit() time.sleep(delay) print ("%s: %s" %(threadName, time.ctime(time.time()))) counter -= 1 # Create new threads thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() print ("Exiting Main Thread")
執行結果:ui
$ ./threading_subclass.py Starting Thread-1 Starting Thread-2 Exiting Main Thread Thread-1: Tue Sep 15 11:03:21 2015 Thread-2: Tue Sep 15 11:03:22 2015 Thread-1: Tue Sep 15 11:03:22 2015 Thread-1: Tue Sep 15 11:03:23 2015 Thread-2: Tue Sep 15 11:03:24 2015 Thread-1: Tue Sep 15 11:03:24 2015 Thread-1: Tue Sep 15 11:03:25 2015 Exiting Thread-1 Thread-2: Tue Sep 15 11:03:26 2015 Thread-2: Tue Sep 15 11:03:28 2015 Thread-2: Tue Sep 15 11:03:30 2015 Exiting Thread-2
python的內置數據結構好比列表和字典等是線程安全的,可是簡單數據類型好比整數和浮點數則不是線程安全的,要這些簡單數據類型的經過操做,就須要使用鎖。spa
#!/usr/bin/env python3 # coding=utf-8 import threading shared_resource_with_lock = 0 shared_resource_with_no_lock = 0 COUNT = 100000 shared_resource_lock = threading.Lock() ####LOCK MANAGEMENT## def increment_with_lock(): global shared_resource_with_lock for i in range(COUNT): shared_resource_lock.acquire() shared_resource_with_lock += 1 shared_resource_lock.release() def decrement_with_lock(): global shared_resource_with_lock for i in range(COUNT): shared_resource_lock.acquire() shared_resource_with_lock -= 1 shared_resource_lock.release() ####NO LOCK MANAGEMENT ## def increment_without_lock(): global shared_resource_with_no_lock for i in range(COUNT): shared_resource_with_no_lock += 1 def decrement_without_lock(): global shared_resource_with_no_lock for i in range(COUNT): shared_resource_with_no_lock -= 1 ####the Main program if __name__ == "__main__": t1 = threading.Thread(target = increment_with_lock) t2 = threading.Thread(target = decrement_with_lock) t3 = threading.Thread(target = increment_without_lock) t4 = threading.Thread(target = decrement_without_lock) t1.start() t2.start() t3.start() t4.start() t1.join() t2.join() t3.join() t4.join() print ("the value of shared variable with lock management is %s"\ %shared_resource_with_lock) print ("the value of shared variable with race condition is %s"\ %shared_resource_with_no_lock)
執行結果:
$ ./threading_lock.py the value of shared variable with lock management is 0 the value of shared variable with race condition is 0
又如:
import random import threading import time logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s', ) class Counter(object): def __init__(self, start=0): self.lock = threading.Lock() self.value = start def increment(self): logging.debug(time.ctime(time.time())) logging.debug('Waiting for lock') self.lock.acquire() try: pause = random.randint(1,3) logging.debug(time.ctime(time.time())) logging.debug('Acquired lock') self.value = self.value + 1 logging.debug('lock {0} seconds'.format(pause)) time.sleep(pause) finally: self.lock.release() def worker(c): for i in range(2): pause = random.randint(1,3) logging.debug(time.ctime(time.time())) logging.debug('Sleeping %0.02f', pause) time.sleep(pause) c.increment() logging.debug('Done') counter = Counter() for i in range(2): t = threading.Thread(target=worker, args=(counter,)) t.start() logging.debug('Waiting for worker threads') main_thread = threading.currentThread() for t in threading.enumerate(): if t is not main_thread: t.join() logging.debug('Counter: %d', counter.value)
執行結果:
$ python threading_lock.py (Thread-1 ) Tue Sep 15 15:49:18 2015 (Thread-1 ) Sleeping 3.00 (Thread-2 ) Tue Sep 15 15:49:18 2015 (MainThread) Waiting for worker threads (Thread-2 ) Sleeping 2.00 (Thread-2 ) Tue Sep 15 15:49:20 2015 (Thread-2 ) Waiting for lock (Thread-2 ) Tue Sep 15 15:49:20 2015 (Thread-2 ) Acquired lock (Thread-2 ) lock 2 seconds (Thread-1 ) Tue Sep 15 15:49:21 2015 (Thread-1 ) Waiting for lock (Thread-2 ) Tue Sep 15 15:49:22 2015 (Thread-1 ) Tue Sep 15 15:49:22 2015 (Thread-2 ) Sleeping 2.00 (Thread-1 ) Acquired lock (Thread-1 ) lock 1 seconds (Thread-1 ) Tue Sep 15 15:49:23 2015 (Thread-1 ) Sleeping 2.00 (Thread-2 ) Tue Sep 15 15:49:24 2015 (Thread-2 ) Waiting for lock (Thread-2 ) Tue Sep 15 15:49:24 2015 (Thread-2 ) Acquired lock (Thread-2 ) lock 1 seconds (Thread-1 ) Tue Sep 15 15:49:25 2015 (Thread-1 ) Waiting for lock (Thread-1 ) Tue Sep 15 15:49:25 2015 (Thread-1 ) Acquired lock (Thread-1 ) lock 2 seconds (Thread-2 ) Done (Thread-1 ) Done (MainThread) Counter: 4
acquire()中傳入False值,能夠檢查是否得到了鎖。好比:
import logging import threading import time logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s', ) def lock_holder(lock): logging.debug('Starting') while True: lock.acquire() try: logging.debug('Holding') time.sleep(0.5) finally: logging.debug('Not holding') lock.release() time.sleep(0.5) return def worker(lock): logging.debug('Starting') num_tries = 0 num_acquires = 0 while num_acquires < 3: time.sleep(0.5) logging.debug('Trying to acquire') have_it = lock.acquire(0) try: num_tries += 1 if have_it: logging.debug('Iteration %d: Acquired', num_tries) num_acquires += 1 else: logging.debug('Iteration %d: Not acquired', num_tries) finally: if have_it: lock.release() logging.debug('Done after %d iterations', num_tries) lock = threading.Lock() holder = threading.Thread(target=lock_holder, args=(lock,), name='LockHolder') holder.setDaemon(True) holder.start() worker = threading.Thread(target=worker, args=(lock,), name='Worker') worker.start()
執行結果:
$ python threading_lock_noblock.py (LockHolder) Starting (LockHolder) Holding (Worker ) Starting (LockHolder) Not holding (Worker ) Trying to acquire (Worker ) Iteration 1: Acquired (LockHolder) Holding (Worker ) Trying to acquire (Worker ) Iteration 2: Not acquired (LockHolder) Not holding (Worker ) Trying to acquire (Worker ) Iteration 3: Acquired (LockHolder) Holding (Worker ) Trying to acquire (Worker ) Iteration 4: Not acquired (LockHolder) Not holding (Worker ) Trying to acquire (Worker ) Iteration 5: Acquired (Worker ) Done after 5 iterations
threading.RLock()
返回可重入鎖對象。重入鎖必須由得到它的線程釋放。一旦線程得到了重入鎖,同一線程可不阻塞地再次得到,獲取以後必須釋放。
一般一個線程只能獲取一次鎖:
import threading lock = threading.Lock() print 'First try :', lock.acquire() print 'Second try:', lock.acquire(0)
執行結果:
$ python threading_lock_reacquire.py First try : True Second try: False
使用RLock能夠獲取屢次鎖:
import threading lock = threading.RLock() print 'First try :', lock.acquire() print 'Second try:', lock.acquire(0)
執行結果:
python threading_rlock.py First try : True Second try: 1
#!/usr/bin/env python3 # coding=utf-8 import threading import time class Box(object): lock = threading.RLock() def __init__(self): self.total_items = 0 def execute(self,n): Box.lock.acquire() self.total_items += n Box.lock.release() def add(self): Box.lock.acquire() self.execute(1) Box.lock.release() def remove(self): Box.lock.acquire() self.execute(-1) Box.lock.release() ## These two functions run n in separate ## threads and call the Box's methods def adder(box,items): while items > 0: print ("adding 1 item in the box\n") box.add() time.sleep(5) items -= 1 def remover(box,items): while items > 0: print ("removing 1 item in the box") box.remove() time.sleep(5) items -= 1 ## the main program build some ## threads and make sure it works if __name__ == "__main__": items = 5 print ("putting %s items in the box " % items) box = Box() t1 = threading.Thread(target=adder,args=(box,items)) t2 = threading.Thread(target=remover,args=(box,items)) t1.start() t2.start() t1.join() t2.join() print ("%s items still remain in the box " % box.total_items)
執行結果:
$ python3 threading_rlock2.py putting 5 items in the box adding 1 item in the box removing 1 item in the box adding 1 item in the box removing 1 item in the box adding 1 item in the box removing 1 item in the box removing 1 item in the box adding 1 item in the box removing 1 item in the box adding 1 item in the box 0 items still remain in the box