python自学-class22(up)-python线程基础学习

python线程基础学习

1. 单线程
2. 多线程并发
3. 传递参数
4. 主线程与小弟线程
5. 多线程速度
6. 线程冲突
7. 基于类实现多线程
8. 类线程的顺序执行风格
9. 类线程的乱序执行风格
10. 基于类解决线程冲突(撞车问题)
11. 死锁
12. RLOCK解决单线程死锁
13. 创建多线程的方式
14. 信号量限制线程数量
15. 栅栏锁定匹配线程数量
*

+++++++++++++++++++++++++++++++++++++++++
1.单线程:
单线程即什么活都是一个人干,效率较低,在之前的学习中,程序全都是单线程运行的。

import win32api  #引用系统函数
#0代表系统,  "你的账户很危险"代表内容,  "来自支付宝的问候"代表标题,   0-4代表对话类型
win32api.MessageBox(0,"你的账户很危险","来自支付宝的问候",2)

2.多线程并发:
多线程即多了人手同时工作,解决一件事情速度加快,但需要主要的是,并发可能会导致乱序;

import win32api   #引用系统函数
import _thread    #多线程
def show():
    win32api.MessageBox(0, "你的账户很危险", "来自支付宝的问候", 2)
#顺序执行
#for i in range(5):
#   show()
for i in range(5):
    _thread.start_new_thread(show,())   #()元组,用于传递参数
show()

3.使用多线程时传递参数:

import win32api   #引用系统函数
import _thread    #多线程
def show(i):
    win32api.MessageBox(0, "你的账户很危险"+str(i), "来自支付宝的问候", 2)
#顺序执行
#for i in range(5):
#   show()
for i in range(5):
    _thread.start_new_thread(show,(i,))   #()元组,用于传递参数
show(10)

运行效果:
在这里插入图片描述
4.主线程与小弟线程:
主线程停止即所有小弟线程不再干活,而小弟线程停止不会使主线程崩溃;这里体现的方式是,在关停所有小窗口(小弟线程)后,程序仍然在运行;

import win32api   #引用系统函数
import _thread    #多线程
def show(i):
    win32api.MessageBox(0, "你的账户很危险"+str(i), "来自支付宝的问候", 2)
#顺序执行
#for i in range(5):
#   show()
#主线程,主线程停止后小弟线程不显示
for i in range(5):
    _thread.start_new_thread(show,(i,))   #()元组,用于传递参数
#阻塞,让主线程不死
while True:
    pass

5.多线程的速度
多线程由于并发执行,一般而言速度会比单线程执行快许多,测试代码如下:

import _thread
import time
def go():
    for i in range(10):
        print(i,"---------")
        time.sleep(1)
#for i in range(5):   #50秒
#    go()
for i in range(5):
    _thread.start_new_thread(go,()) #10秒
for i in range(12):
    time.sleep(1)
print("game,over")

6.线程冲突问题:
由于多线程的并发操作,那么各个线程同时运行必定会导致抢占资源而冲突;

import _thread
import time
num=0
def add():
    global num
    for i in range(10000):
        num+=1
    print(num)
'''
for i in range(5):
    add()
'''
#不报错,但是结果不正确
for i in range(5):
    _thread.start_new_thread(add,())
while True:
    pass

7.基于类实现多线程:
使用类封装多线程,需要继承

import threading
import time
import win32api
class Mythread(threading.Thread):      #继承threading.Thread
    def run(self):    #run重写
        win32api.MessageBox(0,"你的账户很危险","来自支付宝的问候",2)
for i in range(5):
    t=Mythread()   #初始化
    t.start()    #开启

while True:
    pass

8.类线程的顺序执行风格:
为了解决线程并发冲突的问题,可以使用join()顺序执行风格:

import threading
import time
import win32api
class Mythread(threading.Thread):      #继承threading.Thread
    def run(self):    #run重写
        win32api.MessageBox(0,"你的账户很危险","来自支付宝的问候",2)

for i in range(5):
    t=Mythread()   #初始化
    t.start()    #开启
    t.join()   #主线程等待线程t执行完成,解决线程冲突的一种方法

9.类线程的乱序执行风格:

import threading
import time
import win32api
class Mythread(threading.Thread):      #继承threading.Thread
    def run(self):    #run重写
        win32api.MessageBox(0,"你的账户很危险","来自支付宝的问候",2)

mythread=[]  #list
for i in range(5):
    t=Mythread()   #初始化
    t.start()
    mythread.append(t)   #加入线程集合


for mythd in mythread:  #mysthd 是一个线程
    t.join()   #主线程等待线程t完成,不需要阻塞
print("over")

10.基于类解决线程冲突:
这里是使用了LOCK()来解决线程冲突的问题,也即锁住资源,在锁定期间,其他人不能干活,但是可能会导致死锁问题,即一直锁住,谁都干不了活

import threading
import time

num=0
mutex=threading.Lock()   #创建一个锁
class Mythread(threading.Thread):
    def run(self):
        global num
        if mutex.acquire(1):   #锁住成功,没有锁住成功则一直等待,1代表参数,独占
            for i in range(100000):   #锁定期间其他人不能干活
                num+=1
            mutex.release()  #释放锁
        print(num)
mythread=[]
for i in range(5):
    t=Mythread()
    t.start()
    mythread.append(t)
for t in mythread:
    t.join()
print("over!")

11.死锁:
死锁可以形象表述为男女朋友吵架,谁都拉不下脸先道歉,即俩个线程互相锁住资源不释放,然后一直等待对方先道歉(释放),从而形成了死锁;

import threading
import time
boymutex=threading.Lock()  #创建一个锁
girlmutex=threading.Lock()

class boy(threading.Thread):
    def run(self):
        if boymutex.acquire(1):   #锁定成功继续执行,锁定不成功,继续等待
            print("boy  say  i  am  sor  up")
            time.sleep(3)
            if girlmutex.acquire(1):#锁定不成功,一直等待
                print("boy  say  i  am  sor  down")
                girlmutex.release()
            boymutex.release()
class girl(threading.Thread):
    def run(self):
        if girlmutex.acquire(1):#锁定成功继续执行,锁定不成功,继续等待
            print("girl  say  i  am  sor  up")
            time.sleep(3)
            #girlmutex.release()  #放在这儿可以解开死锁,女生先释放
            if boymutex.acquire(1):#锁定不成功,一直等待
                print("gril  say  i  am  sor  down")
                boymutex.release()
            girlmutex.release()

#开启俩个线程
boy1=boy()
boy1.start()
girl1=girl()
girl1.start()

12.解决单线程死锁用RLOCK:

import threading
import time

num=0
#mutex=threading.Lock()  #LOCK
mutex=threading.RLock()  #RLOCK可以避免单线程死锁
class Mythread(threading.Thread):
    def run(self):
        global num
        if mutex.acquire(1):
            num=num+1
            print(self.name,num)
            if mutex.acquire(1):   #这里形成了死锁
                num+=1000
                mutex.release()
            mutex.release()

for i in range(5):  #开启五个线程
    t=Mythread()
    t.start()

13.创建多线程的方式:
有三种方式:一是函数方式,二是类的继承方式,三是类方式

'''
#第一种风格:函数创建,不考虑冲突与通信
import win32api   #引用系统函数
import _thread    #多线程

def show():
    win32api.MessageBox(0, "你的账户很危险", "来自支付宝的问候", 2)
#顺序执行
#for i in range(5):
#   show()
for i in range(5):
    _thread.start_new_thread(show,())   #()元组,用于传递参数
show()
'''
#第二种风格用类来创建,通过继承实现
import threading
import time
import win32api
class Mythread(threading.Thread):      #继承threading.Thread
    def __init__(self,num):
        threading.Thread.__init__(self)#父类初始化
        self.num=num
    def run(self):    #run重写
        win32api.MessageBox(0,"你的账户很危险"+str(self.num),"来自支付宝的问候",2)

for i in range(5):
    t=Mythread(i)   #初始化
    t.start()    #开启
    t.join()   #主线程等待线程t执行完成,解决线程冲突的一种方法

'''
#第三种风格也是类构建,target=show线程函数,args=()参数
import win32api   #引用系统函数
import threading
def show(i):
    win32api.MessageBox(0, "你的账户很危险"+str(i), "来自支付宝的问候", 2)

threading.Thread(target=show,args=(1,)).start()
threading.Thread(target=show,args=(2,)).start()
threading.Thread(target=show,args=(3,)).start()
'''

14.信号量限制线程数量
在需要干的活比较多时,也不能任由线程数量无限增长,因此需要限制线程数量,第一种方式是通过信号量来限制线程数量,即限定最大进程数量,当达到最大线程数量时,后来者需要等待前面线程完成释放资源,才能执行。

import threading
import time
sem=threading.Semaphore(2)#限制线程最大数量为2个

def gothread():
    with sem:  #锁定数量
        for i in range(10):
            print(threading.current_thread().name,i)
            time.sleep(1)

for i in range(5):
    threading.Thread(target=gothread).start()

15.栅栏锁定匹配线程数量
第二种·是通过栅栏锁定匹配线程数量,即为了合理使用资源,限定必须n个线程准备才能一起执行,不到n个线程则一起等待,即类似栅栏的效果。

import threading
import time
#为了合理利用资源,必须n个线程一起执行
bar = threading.Barrier(2)  #必须凑一对才能一起执行

def saver():
    print(threading.current_thread().name, "satrt")
    time.sleep(3)
    bar.wait()
    print(threading.current_thread().name, "end")

for i in range(5):
    threading.Thread(target=saver).start()

总结:

线程的知识实际花了不止一天,而不是一个上午,因为比较重要,感觉前面的爬虫,数据检索都可以用多线程来高效实现。

猜你喜欢

转载自blog.csdn.net/weixin_46837674/article/details/113826613