1. 程式人生 > >執行緒(二):執行緒開啟方式與多執行緒(threading模組)

執行緒(二):執行緒開啟方式與多執行緒(threading模組)

目錄

執行緒的建立Threading.Thread類

1)執行緒的建立

2)多執行緒與多程序

3)Thread類的其他方法

4)守護執行緒


multiprocess模組的完全模仿了threading模組的介面,二者在使用層面,有很大的相似性,因而不再詳細介紹(官方連結

執行緒的建立Threading.Thread類

1)執行緒的建立

#建立執行緒的方式1
from threading import Thread
import time
def sayhi(name):
    time.sleep(2)
    print('%s say hello' %name)

if __name__ == '__main__':
    t=Thread(target=sayhi,args=('egon',))
    t.start()
    print('主執行緒')



#建立執行緒的方式2(類形式)

from threading import Thread
import time
class Sayhi(Thread):
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):
        time.sleep(2)
        print('%s say hello' % self.name)


if __name__ == '__main__':
    t = Sayhi('egon')
    t.start()
    print('主執行緒')

2)多執行緒與多程序

#pid的比較
from threading import Thread
from multiprocessing import Process
import os

def work():
    print('hello',os.getpid())

if __name__ == '__main__':
    #part1:在主程序下開啟多個執行緒,每個執行緒都跟主程序的pid一樣
    t1=Thread(target=work)
    t2=Thread(target=work)
    t1.start()
    t2.start()
    print('主執行緒/主程序pid',os.getpid())

    #part2:開多個程序,每個程序都有不同的pid
    p1=Process(target=work)
    p2=Process(target=work)
    p1.start()
    p2.start()
    print('主執行緒/主程序pid',os.getpid())

#開啟效率的較量
from threading import Thread
from multiprocessing import Process
import os

def work():
    print('hello')

if __name__ == '__main__':
    #在主程序下開啟執行緒
    t=Thread(target=work)
    t.start()
    print('主執行緒/主程序')
    '''
    列印結果:
    hello
    主執行緒/主程序
    '''

    #在主程序下開啟子程序
    t=Process(target=work)
    t.start()
    print('主執行緒/主程序')
    '''
    列印結果:
    主執行緒/主程序
    hello
    '''

#記憶體資料的共享問題
from  threading import Thread
from multiprocessing import Process
import os
def work():
    global n
    n=0

if __name__ == '__main__':
    # n=100
    # p=Process(target=work)
    # p.start()
    # p.join()
    # print('主',n) #毫無疑問子程序p已經將自己的全域性的n改成了0,但改的僅僅是它自己的,檢視父程序的n仍然為100


    n=1
    t=Thread(target=work)
    t.start()
    t.join()
    print('主',n) #檢視結果為0,因為同一程序內的執行緒之間共享程序內的資料
同一程序內的執行緒共享該程序的資料?

練習 :多執行緒實現socket

server端
#_*_coding:utf-8_*_
#!/usr/bin/env python
import multiprocessing
import threading

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',8080))
s.listen(5)

def action(conn):
    while True:
        data=conn.recv(1024)
        print(data)
        conn.send(data.upper())

if __name__ == '__main__':

    while True:
        conn,addr=s.accept()


        p=threading.Thread(target=action,args=(conn,))
        p.start()



client端

#_*_coding:utf-8_*_
#!/usr/bin/env python


import socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('127.0.0.1',8080))

while True:
    msg=input('>>: ').strip()
    if not msg:continue

    s.send(msg.encode('utf-8'))
    data=s.recv(1024)
    print(data)

3)Thread類的其他方法

Thread例項物件的方法
  ● isAlive(): 返回執行緒是否活動的。
  ● getName(): 返回執行緒名。
  ● setName(): 設定執行緒名。

threading模組提供的一些方法:
  ● threading.currentThread(): 返回當前的執行緒變數。
  ● threading.enumerate(): 返回一個包含正在執行的執行緒的list。正在執行指執行緒啟動後、結束前,不包括啟動前和終止後的執行緒。
  ● threading.activeCount(): 返回正在執行的執行緒數量,與len(threading.enumerate())有相同的結果。

#程式碼示例
from threading import Thread
import threading
from multiprocessing import Process
import os

def work():
    import time
    time.sleep(3)
    print(threading.current_thread().getName())


if __name__ == '__main__':
    #在主程序下開啟執行緒
    t=Thread(target=work)
    t.start()

    print(threading.current_thread().getName())
    print(threading.current_thread()) #主執行緒
    print(threading.enumerate()) #連同主執行緒在內有兩個執行的執行緒
    print(threading.active_count())
    print('主執行緒/主程序')

    '''
    列印結果:
    MainThread
    <_MainThread(MainThread, started 140735268892672)>
    [<_MainThread(MainThread, started 140735268892672)>, <Thread(Thread-1, started 123145307557888)>]
    主執行緒/主程序
    Thread-1
    '''

#join方法
from threading import Thread
import time
def sayhi(name):
    time.sleep(2)
    print('%s say hello' %name)

if __name__ == '__main__':
    t=Thread(target=sayhi,args=('egon',))
    t.start()
    t.join()
    print('主執行緒')
    print(t.is_alive())
    '''
    egon say hello
    主執行緒
    False
    '''

4)守護執行緒

無論是程序還是執行緒,都遵循:守護xx會等待主xx執行完畢後被銷燬。需要強調的是:執行完畢並非終止執行

1.對主程序來說,執行完畢指的是主程序程式碼執行完畢
2.對主執行緒來說,執行完畢指的是主執行緒所在的程序內所有非守護執行緒統統執行完畢,主執行緒才算執行完畢

詳細解釋

1 主程序在其程式碼結束後就已經算執行完畢了(守護程序在此時就被回收),然後主程序會一直等非守護的子程序都執行完畢後回收子程序的資源(否則會產生殭屍程序),才會結束,

2 主執行緒在其他非守護執行緒執行完畢後才算執行完畢(守護執行緒在此時就被回收)。因為主執行緒的結束意味著程序的結束,程序整體的資源都將被回收,而程序必須保證非守護執行緒都執行完畢後才能結束。

#守護執行緒例1
from threading import Thread
import time
def sayhi(name):
    time.sleep(2)
    print('%s say hello' %name)

if __name__ == '__main__':
    t=Thread(target=sayhi,args=('egon',))
    t.setDaemon(True) #必須在t.start()之前設定
    t.start()

    print('主執行緒')
    print(t.is_alive())
    '''
    主執行緒
    True
    '''


#守護執行緒例2
from threading import Thread
import time
def foo():
    print(123)
    time.sleep(1)
    print("end123")

def bar():
    print(456)
    time.sleep(3)
    print("end456")


t1=Thread(target=foo)
t2=Thread(target=bar)

t1.daemon=True
t1.start()
t2.start()
print("main-------")