python threading多线程速成学习


多线程可以加速程序的运算,此笔记为python的多线程模块threading的学习笔记。来自莫凡大神视频学习笔记 莫凡python-threading

添加线程

import threading
threading.active_count()#获取已经激活的线程数
# 1
threading.enumerate()#查看所有的线程信息
# [<_MainThread(MainThread, started 4088)>]
#多线程为一个_MainThread带多个Thread
threading.current_thread()#查看当前运行的进程
# <_MainThread(MainThread, started 11136)>

#添加线程threading.Thread()
#接收参数target代表这个线程要完成的任务,需自行定义
def target_job():
    print("This is a thread of %s"%threading.current_thread())
def main():
    thread=threading.Thread(target=target_job,)#定义线程
    thread.start()#线程工作

main( )
#This is a thread of <Thread(Thread-1, started 12692)>

join之进程执行的顺序

import threading
import time
def thread( ):
    print("T START")
    for i in range(100):
        time.sleep(0.1)
    print("T end")

add_thread=threading.Thread(target=thread,name='T')
add_thread.start()
print("all over")
实际执行效果:
T START
all over
T end
线程任务还未完成便输出all over
import threading
import time
def thread( ):
    print("T START")
    for i in range(100):
        time.sleep(0.1)
    print("T end")

add_thread=threading.Thread(target=thread,name='T')
add_thread.start()
add_thread.join()#加入join,遵循顺序输出
print("all over")
T START
T end
all over

当两个线程时,由于任务2比任务1轻量级,会率先完成,且all over 的执行顺序取决于其他线程的执行速度。如下所示:

def thread1( ):
    print("T1 START")
    for i in range(10):
        time.sleep(0.1)
    print("T1 end")

def thread2( ):
    print("T2 START")
    print("T2 end")
add_thread1=threading.Thread(target=thread1,name='T1')
add_thread2=threading.Thread(target=thread2,name='T2')
add_thread1.start()
add_thread2.start()
print("all over")
结果:
T1 START
T2 START
all over
T2 end
T1 end

当T1加入join后:

add_thread1=threading.Thread(target=thread1,name='T1')
add_thread2=threading.Thread(target=thread2,name='T2')
add_thread1.start()
add_thread1.join()
add_thread2.start()
print("all over")
结果:
T1 START
T1 end
T2 START
T2 end
all over

当T2加入join后,下面1122的加法会使得轻量级任务率先完成。但all over还是最后执行。

dd_thread1=threading.Thread(target=thread1,name='T1')
add_thread2=threading.Thread(target=thread2,name='T2')
add_thread1.start()
add_thread2.start()
add_thread1.join()
add_thread2.join()
print("all over")
结果:
T1 START
T2 START
T2 end
T1 end
all over

当采用1212加法后,遵循正常顺序

add_thread1=threading.Thread(target=thread1,name='T1')
add_thread2=threading.Thread(target=thread2,name='T2')
add_thread1.start()
add_thread1.join()
add_thread2.start()
add_thread2.join()
print("all over")
结果:
T1 START
T1 end
T2 START
T2 end
all over

存储进程结果Queue

导入线程,队列的标准模块
定义一个被多线程调用函数
定义一个多线程函数

import threading
import time
from queue import  Queue
#将数据列表数据传入,四此案成处理,结果保存在Queue中,线程执行完后,
# 从Queue中获取存储结果

#多线程调用的函数不能用return返回值
#被多线程调用的函数
def work(l,q):
    for i in range(len(l)):
        l[i]=l[i]**2
    q.put(l)

#定义多线程函数,定义4个线程
def multi_thread():
    q=Queue()#q中存放返回值
    threads=[]#存放4线程
    data=[[1,2,3],[4,5,6],[7,8,9],[3,4,5]]
    #定义线程
    for i in range(4):
        Ts = threading.Thread(target=work, args=(data[i],q))
        Ts.start()
        threads.append(Ts)#每个线程append列表中
    #执行线程
    for t in threads:
        t.join( )
    #用空列表接收队列中的结果
    results=[]
    for _ in range(4):
        results.append(q.get())
    print(results)

multi_thread()
结果:
[[1, 4, 9], [16, 25, 36], [49, 64, 81], [9, 16, 25]]

GIL(Global Interpreter Lock)

GIL让python任何时候只能执行一个python线程,因为解释器的C语言实现部分在完全并行执行时并不是线程安全的,解释器被一个全局解释器锁保护。GIL最大的问题时python的多线程程序不能利用多核CPU优势,影响到那些严重依赖CPU的程序。

import threading
import copy
import time
from queue import  Queue

#多线程调用的函数不能用return返回值
#被多线程调用的函数
def work(l,q):
    res=sum(l)
    q.put(res)

#定义多线程函数,定义4个线程
def multi_thread(I):
    q=Queue()#q中存放返回值
    threads=[]#存放4线程
    #定义线程
    for i in range(4):
        Ts = threading.Thread(target=work, args=(copy.copy(I),q),name="T%i"%i)
        Ts.start()
        threads.append(Ts)#每个线程append列表中
    #执行线程
    for t in threads:
        t.join( )
    total=0
    for _ in range(4):
        total=total+q.get()
    print(total)

#定义一个普通函数
def f(I):
    s=sum(I)
    print(s)
I=list(range(10000))
t=time.time()
f(I*4)
print("normal:",time.time()-t)
t2=time.time()
multi_thread(I)
print("multithreading:",time.time()-t2)
结果:
99980000
normal: 0.0010018348693847656
199980000
multithreading: 0.001976490020751953

理应利用多线程会变快,但并没有。

线程锁lock

不使用LOCK,打印混乱,使用lock,利用acquire,release将共享内存上锁,确保内存独占性。

import threading
def work1():
    global a
    lock.acquire()
    for i in range(10):
        a=a+1
        print("work1",a)
    lock.release()
def work2():
    global a
    lock.acquire()
    for i in range(10):
        a = a + 10
        print("work2", a)
    lock.release()


lock=threading.Lock( )
a=0
w1=threading.Thread(target=work1)
w2=threading.Thread(target=work2)
w1.start()
w2.start()
w1.join()
w2.join()
结果:
work1 1
work1 2
work1 3
work1 4
work1 5
work1 6
work1 7
work1 8
work1 9
work1 10
work2 20
work2 30
work2 40
work2 50
work2 60
work2 70
work2 80
work2 90
work2 100
work2 110

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值