Python 第七天(多线程)

线程

线程是程序最小的执行单元;一个进程可以有多个线程,但是只有一个主线程

Python的标准库提供了两个模块:thread和threading,thread是低级模块,threading是高级模块,对thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。

Thread

import _thread  # 多线程
import time
def go():
    for i in range(5):
        print(i,"-------")
        time.sleep(1)
for i in range(5):   # 同时执行5次
    _thread.start_new_thread(go,())  # 前面是执行函数,后面是一个元组,可以不写前提是函数没有形参

for j in range(6): # 让主线程卡顿6秒
    time.sleep(1)

print("over")

基于类实现多线程

import threading

class haha(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.num = 0

    def run(self):  
        for _ in range(1000):
            self.num += 1
        print(self.num)

if __name__ =="__main__":
    ts = []
    for i in range(5):
        t = haha()
        t.start()
        ts.append(t)

    for i in ts:
        t.join()

    print('Over')

运行结果
运行结果

线程锁

多个线程之间 内存是共享的,所以线程比进程轻量。多个线程是可以同时访问内存中的数据的,如果多个线程同时修改一个对象,那这份数据可能会被破坏,Python的threading类中提供了Lock方法,它会返回一个锁对象,一般通过lock.acquire()来获取锁,通过lock.release()来释放锁,对于那种只允许一个线程操作 的数据,一般把对其的操作放在lock.acquire()和lock.release()中间。

import threading
num = 0
mutex = threading.Lock()  # 创建一个锁,threading.Lock()是一个类

class Myhtread(threading.Thread):
    def run(self):
        global num
        if mutex.acquire(1):  # 如果锁成功,那么线程继续干活,如果锁失败,下面的线程一直等待锁成功,1,代表独占
            for i in range(1000):  # 数字小的时候还是不会产生线程冲突的
                num += 1
            mutex.release()  # 释放锁,一定切记
        print(num)

mythread = []
for i in range(5):
    t = Myhtread()
    t.start()
    mythread.append(t)

for thread in mythread:
    thread.join() 
print("game over")

信号限制线程数

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()

锁定匹配数量

import threading
# 为了合理利用资源
# 凑出线程数量,也就是说一定要至少凑成两个才能执行
# 换而言之,也就是说只有创建线程数是2,或者2的倍数才能全部执行
bar = threading.Barrier(2)

def sever():
    print(threading.current_thread().name,"start")
    bar.wait()
    print(threading.current_thread().name,"end")

for i in range(3):
    threading.Thread(target=sever).start()

俩个例子

# 随机生成100个验证码存入本地
import threading
import random

class Myhtread(threading.Thread):
    def __init__(self,lock):
        threading.Thread.__init__(self)
        self.lock = lock
        self.list_ = []
    def run(self):
        for i in range(50):
            res = random.randint(1000,10000)
            self.list_.append(res)
        with self.lock:
            self.write(self.list_)
    
    def write(self,num):
        b = [str(x)+'\n' for x in num]
        b = ''.join(b)
        with open('res.txt',mode = 'a') as file:
            file.write(b)

if __name__ =="__main__":
    ts = []
    lock = threading.Lock()
    for i in range(2):
        t = Myhtread(lock)
        t.start()
        ts.append(t)
    for t in ts:
        t.join()

    print("Over")
# 获取猫眼榜单top—100的电影名字和评分存入本地
import requests
import re
import threading

class maoyan_top100(threading.Thread):
    def __init__(self,start_,end_,lock):
        threading.Thread.__init__(self)
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
        }
        self.base_url = "https://maoyan.com/board/4?offset=%d"
        self.start_ = start_
        self.end_ = end_
        self.lock = lock

    def run(self):
        for offset in range(self.start_,self.end_,10):
            url = self.base_url % offset
            response = requests.get(self.base_url, headers=self.headers)
            html = response.text
            info_list =  self.get_Information(html)
            with self.lock:
                self.write(info_list)
            print("offser {} is ok!".format(offset))

    def get_Information(self,html):
        information_list = []
        for line in html.split('\n'):
            if 'class="image-link"' in line:
                move_name = line.split('title="')[1].split('"')[0]
                print(move_name)
            if 'class="integer"' in line:
                res = re.search(
                    '<p class="score"><i class="integer">(\d\.)</i><i class="fraction">(\d)</i></p>',
                    line)
                integer = res.group(1)
                fraction = res.group(2)
                score = integer + fraction
                information_list.append(score)
        return information_list
    
    def write(self,info_list):
        str_ = str(info_list) + '\n'
        with open('move.txt',mode='a',encoding='utf8') as file:
            file.write(str_)

if __name__ == "__main__":
    threads = []
    lock = threading.Lock()
    for i in range(2):
        t = maoyan_top100(start_=i * 50, end_=(i + 1) * 50,lock=lock)
        t.start()
        threads.append(t)
    for t in threads:
        t.join()

    print("Over")

线程通信(event)

import threading
import time

def A(e):
    e.wait()
    print("Hello")

def B(self):
    time.sleep(3)
    e.set()

if __name__=="__main__":
    e = threading.Event()
    t1 = threading.Thread(target=A,args=(e,))
    t2 = threading.Thread(target=B,args=(e,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

例子

import threading
import time

def deco2(times):
    def deco(func):
        def warp(*args,**kwargs):
            e = args[0]
            time.sleep(times)
            e.set()
            return func(*args,**kwargs)
        return warp
    return deco

@deco2(5)
def A(e):
    e.wait()
    print('Hello World!')

if __name__=="__main__":
    e = threading.Event()
    t = threading.Thread(target=A,args=(e,))
    t.start()
    t.join()

运行结果
运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值