python之线程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之线程相关的知识,希望对你有一定的参考价值。

什么是线程

线程是应用程序中工作的最小单元,或者称之为微进程.它是进程的实际运作单位,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

run(): 用以表示线程活动的方法。
start():启动线程活动。 
join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
setDaemon(True):守护主线程,跟随主线程退(必须要放在start()上方)
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。

开启线程的两种方式

技术分享图片
from threading import Thread

def f1(n):
    print("%s号线程"%n)

def f2(n):
    print("%s号线程"%n)

if __name__ == __main__:
    p1 = Thread(target=f1,args=(1,))
    p2 = Thread(target=f1, args=(2,))
    p1.start()
    p2.start()

    print("主线程")
第一种方式
技术分享图片
from threading import Thread
class Mythread(Thread):
    def __init__(self,name):
        super(Mythread, self).__init__()
        self.name = name

    def run(self):
        print("%s号线程"%self.name)


if __name__ == __main__:
    p1 = Mythread("alex")
    p1.start()


    print("主线程")
第二种方式

查看线程的进程

技术分享图片
import os
from threading import Thread

def f1(n):
    print("1号",os.getpid())
    print(%s号线程任务%n)

def f2(n):
    print(2号,os.getpid())
    print(%s号线程任务%n)

if __name__ == __main__:
    t1 = Thread(target=f1,args=(1,))
    t2 = Thread(target=f2,args=(2,))
    t1.start()
    t2.start()
    print(主线程,os.getpid())
    print(主线程)
pid

验证线程数据共享

技术分享图片
import time
from threading import Thread

num =100
def f1():
    time.sleep(3)
    global num
    num = 3
    print(子线程num,num)

if __name__ == __main__:
    t = Thread(target=f1)
    t.start()
    t.join()
    print("主线程中的num",num)
View Code

线程与进程的效率对比

技术分享图片
# -*- coding:utf-8 -*-
import time
from threading import Thread
from multiprocessing import Process

def f1():
    n = 10
    for i in range(100):
        n+=i

if __name__ == __main__:
    t_s_time = time.time()
    t_list = []
    for i in range(20):
        t = Thread(target= f1,)
        t.start()
        t_list.append(t)
    [tt.join() for tt in t_list]
    t_e_time = time.time()
    t_dir_time = t_e_time - t_s_time

    p_s_time = time.time()
    p_list = []
    for i in range(20):
        p = Process(target=f1,)
        p.start()
        p_list.append(p)

    [pp.join() for pp in p_list]
    p_e_time = time.time()
    p_dir_time = p_e_time - p_s_time
    print("多线程执行时间:",t_dir_time)
    print("多进程执行时间:",p_dir_time)
View Code

守护线程

守护线程会等待主程序运行完毕后被销毁

运行完毕并非运行终止

技术分享图片
import time
from threading import Thread
from multiprocessing import Process

# 守护进程:主进程代码执行运行结束,守护进程随之结束
#守护线程:守护线程会等待所有非守护线程运行结束才结束

def f1():
    time.sleep(2)
    print(1号进程)

def f2():
    time.sleep(3)
    print(2号进程)

if __name__ == __main__:
    t1 = Thread(target=f1,)
    t2 = Thread(target=f2,)
    t1.daemon = True
    t2.daemon = True
    t1.start()
    t2.start()
    print(主线程)


# if __name__ == ‘__main__‘:
#     p1 = Process(target=f1,)
#     p2 = Process(target=f2,)
    # p1.daemon = True
    # p2.daemon = True
    # p1.start()
    # p2.start()
    # print("主进程")
View Code

GIL锁

GIL本质是一把互斥锁

技术分享图片
# -*- coding:utf-8 -*-
import time
from threading import Lock ,Thread

num =100
def f1(loc):
    loc.acquire()
    global num
    tmp = num
    tmp -= 1
    time.sleep(0.001)
    num = tmp
    loc.release()

if __name__ == __main__:
    t_loc = Lock()
    t_list = []
    for i in range(10):
        t = Thread(target=f1,args=(t_loc,))
        t.start()
        t_list.append(t)
    [tt.join() for tt in t_list]

    print("主线程num",num)
Lock锁
技术分享图片
from threading import Thread,Lock,RLock
import time

def f1(locA,locB):

    locA.acquire()
    print("f1>>>1号抢到了A锁")
    time.sleep(1)
    locB.acquire()
    print("f1>>>1号抢到了B锁")
    locB.release()
    locA.release()


def f2(locA,locB):
    locB.acquire()
    print("f2>>>2号抢到了B锁")
    locA.acquire()
    time.sleep(1)
    print("f2>>>2号抢到了A锁")
    locA.release()
    locB.release()

if __name__ == __main__:
    locA = Lock()
    locB = Lock()
    t1 = Thread(target=f1,args=(locA,locB))
    t2 = Thread(target=f2,args=(locA,locB))
    t1.start()
    t2.start()
锁死现象
技术分享图片
# -*- coding:utf-8 -*-
from threading import Thread,Lock,RLock
import time

def f1(locA,locB):

    locA.acquire()
    print("f1>>>1号抢到了A锁")
    time.sleep(1)
    locB.acquire()
    print("f1>>>1号抢到了B锁")
    locB.release()
    locA.release()


def f2(locA,locB):
    locB.acquire()
    print("f2>>>2号抢到了B锁")
    locA.acquire()
    time.sleep(1)
    print("f2>>>2号抢到了A锁")
    locA.release()
    locB.release()

if __name__ == __main__:

    locA = locB = RLock()
    t1 = Thread(target=f1,args=(locA,locB))
    t2 = Thread(target=f2,args=(locA,locB))
    t1.start()
    t2.start()
递归锁

信号量Semaphore

技术分享图片
import time,os
from threading import Thread,Semaphore

def func():
    sm.acquire()
    print("get sm")
    time.sleep(1)
    sm.release()
if __name__ == __main__:
    sm = Semaphore(os.cpu_count())
    for i in range(23):
        t = Thread(target=func)
        t.start()
View Code

Event

技术分享图片
from threading import Event
e = Event() #初始状态False
print(e.is_set())

print(开始等待)
e.set() #将事件对象的状态改为True
# e.clear() #将事件对象的状态改为false
e.wait() #当e对象的状态为False的时候会在这个地方阻塞,改为true之后就直接往下执行
print(结束)
View Code

 

以上是关于python之线程的主要内容,如果未能解决你的问题,请参考以下文章

python多线程

python之 多线程

Python之如何优雅的重试

python threading超线程使用简单范例的代码

python高性能代码之多线程优化

[Python3] 043 多线程 简介