【Python】多線程-2
1、 進程和線程的區別:
(1) 一個進程可以有多個線程,一個進程中的多個線程共享該進程的所有資源,多線程切換比多進程切換快,因為不用上下文切換,Python中並發建議用多進程
(2) 進程是資源分配的最小單位,線程是程序執行的最小單位
(3) 進程有自己的獨立地址空間,而線程是共享進程中的數據
2、 並行和並發:並行指在某一秒,並發指在某一時間段
3、 Pip list 查看各API版本號
4、 守護線程:比如主線程A中創建了子線程B,並且在主線程A中調用了B.setDeamon(),意思是,把B設置為守護線程,這時候,要是主線程A執行結束了,就不管子線程B是否完成,一並和主線程A退出。這就是 setDaemon方法的含義, 這基本和 join是相反的。此外,還有個要特別註意必須在 start()方法調用之前調用此方法,如果不設置為守護線程程序有可能會被無線掛起
5、 線程創建的方法:
(1) threading.Thread創建
(2) 通過繼承Thread類創建線程 : class MyThread(threading.Thread)
6、 線程擁有的方法:
(1) isAlive() 返回線程是否在運行。運行指啟動後,結束前。
(2) getName() 獲取線程名字
(3) setName() 設置線程名字
(4) isDeamon() 判斷線程是否隨主線程一起結束
(5) setDeamon() 設置是否為守護線程
(6) start() 啟動線程
(7) join() 等待所有子線程執行完後才能接著往下執行
(8) run()
(9) pool.map()
7、 並發線程的兩種關系:同步與互斥
(1) 鎖可以實現線程間的互斥
(2) 生產者和消費者是線程同步的例子
8、 線程加鎖:threading.Semaphore()
#練習:守護進程 import multiprocessing import time, logging import sys def daemon(): p = multiprocessing.current_process() print ‘Starting:‘, p.name, p.pid sys.stdout.flush() # 將緩沖區數據寫入終端 # time.sleep(2) print ‘Exiting :‘, p.name, p.pid sys.stdout.flush() def non_daemon(): p = multiprocessing.current_process() print ‘non_Starting:‘, p.name, p.pid sys.stdout.flush() print ‘non_Exiting :‘, p.name, p.pid sys.stdout.flush() if __name__ == ‘__main__‘: # 設置日誌輸出到控制臺 multiprocessing.log_to_stderr() logger = multiprocessing.get_logger() # 設置輸出日誌的級別 logger.setLevel(logging.DEBUG) d = multiprocessing.Process(name=‘daemon‘, target=daemon) d.daemon = True n = multiprocessing.Process(name=‘non-daemon‘, target=non_daemon) n.daemon = False d.start() time.sleep(1) n.start() # d.join(1) # n.join() print ‘d.is_alive()‘, d.is_alive() print "n.is_alive()", n.is_alive() print "main Process end!" #練習:線程池 import time from multiprocessing.dummy import Pool as ThreadPool #ThreadPool表示給線程池取一個別名ThreadPool def run(fn): time.sleep(2) print fn if __name__ == "__main__": testFL = [1,2,3,4,5] #創建10個容量的線程池並發執行 pool = ThreadPool(10) pool.map(run,testFL) pool.close() pool.join() #練習:鎖可以實現線程間的互斥 import threading import time data = 0 lock = threading.Lock()#創建一個鎖對象 def func() : global data print "%s acquire lock...\n" %threading.currentThread().getName() if lock.acquire : #if 1:改成這個耗時會長 print "%s get lock...\n" %threading.currentThread().getName() for i in range(100000): data += 1 #must lock #time.sleep(2)#其它操作 print "%s release lock...\n" %threading.currentThread().getName() #調用release()將釋放鎖 #lock.release() startTime = time.time() t1 = threading.Thread(target = func) t2 = threading.Thread(target = func) t3 = threading.Thread(target = func) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join() print data endTime = time.time() print "used time is", endTime - startTime #練習:線程同步 from Queue import Queue #隊列類 import random import threading import time #生成者線程 class Producer(threading.Thread): def __init__(self, t_name, queue): #調用父線程的構造方法。 threading.Thread.__init__(self, name = t_name) self.data = queue def run(self): for i in range(5): print "%s: %s is producing %d to the queue!\n" %(time.ctime(), self.getName(), i) self.data.put(i)#向隊列中添加數據 #產生一個0-2之間的隨機數進行睡眠 time.sleep(random.randrange(10) / 5) print "%s: %s finished!" %(time.ctime(), self.getName()) #消費者線程 class Consumer(threading.Thread): def __init__(self, t_name, queue): threading.Thread.__init__(self, name = t_name) self.data = queue def run(self): for i in range(5): val = self.data.get()#從隊列中取出數據 print "%s: %s is consuming. %d in the queue is consumed!\n" %(time.ctime(), self.getName(), val) time.sleep(random.randrange(10)) print "%s: %s finished!" %(time.ctime(), self.getName()) #Main thread def main(): queue = Queue()#創建一個隊列對象(特點先進先出) producer = Producer(‘Pro.‘, queue)#生產者對象 consumer = Consumer(‘Con.‘, queue)#消費者對象 producer.start() consumer.start() producer.join() consumer.join() print ‘All threads terminate!‘ if __name__ == ‘__main__‘: main() #練習:線程鎖 from threading import Thread, Lock import threading def run(lock, num): lock.acquire() # 獲得鎖 # 取得當前線程的線程名 threadName = threading.current_thread().getName() print "%s, Hello Num: %s" %(threadName, num) lock.release() # 釋放鎖 if __name__ == ‘__main__‘: lock = Lock() # 創建一個共享鎖實例 for num in range(20): Thread(name = ‘Thread-%s‘ %str(num), target = run, args = (lock, num)).start() #練習:多把線程鎖 from threading import Thread,Lock import threading import time def worker(s,i): s.acquire() print(threading.current_thread().name + " acquire") time.sleep(i) print(threading.current_thread().name + " release") s.release() if __name__=="__main__": s=threading.Semaphore(3) for i in range(5): t=Thread(target=worker,args=(s,i*2)) t.start() #t.join #這裏加了join就會逐個執行了
【Python】多線程-2