python多线程

Posted Wualin

tags:

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

多线程

  • 线程之间的数据是共享的

如何开启线程

  • threading模块(使用方法与multiprose一样)
import time
import random
from threading import Thread

def run(name):
    print(‘%s is running‘%name)
    time.sleep(random.randrange(1,5))
    print(‘%s is end‘%name)

if __name__ == ‘__main__‘:
    t1 = Thread(target=run,args=(‘喵‘,))
    t1.start()
    print(‘主线程‘)
import time
from threading import Thread
class MyThread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name

    def run(self):
        print(‘%s is running‘%self.name)
        time.sleep(2)
        print(‘%s is end‘%self.name)

if __name__ == ‘__main__‘:
    t1 = MyThread(‘喵‘)
    t1.start()
    print(‘主线程‘)
thread对象的其他属性与方法
from threading import Thread,currentThread,active_count,enumerate

import time

def task():
    print(‘%s is running‘%currentThread().getName())
    time.sleep(2)
    print(‘%s is done‘%currentThread().getName())

if __name__ == ‘__main__‘:
    t = Thread(target=task,name=‘子线程‘)
    t.start()
    #t.setName(‘儿子进程1‘)  设置线程名字
    print(t.isAlive())#判断线程是否存活
    print(‘主线程‘,currentThread().getName())
    # t.join()#等当前线程结束才继续执行主线程
    print(active_count())   #活跃的线程数
    print(enumerate())#[<_MainThread(MainThread, started 140735697388416)>, <Thread(子线程, started 123145519529984)>]

守护线程

  • 在一个进程内,只有一个线程,线程运行结束,代表这个一个进程结束。
  • 在一个进程内,开多个线程,主线程在代码运行完毕,还需要等待其他线程干完活才会结束

互斥锁

  • 将并行编程串行,牺牲效率保证数据安全,与进程的互斥锁一样使用

GIL全局解释器锁

pass

死锁与递归锁

  • 互斥锁只能acquire一次
from threading import Thread,Lock
import time
mutexA = Lock()
mutexB = Lock()

class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        mutexA.acquire()
        print(‘%s 拿到了A锁‘%self.name)
        mutexB.acquire()
        print(‘%s 拿到了B锁‘%self.name)
        mutexB.release()
        mutexA.release()

    def f2(self):
        mutexB.acquire()
        print(‘%s 拿到了B锁‘ % self.name)
        time.sleep(0.1)
        mutexA.acquire()
        print(‘%s 拿到了A锁‘ % self.name)
        mutexA.release()
        mutexB.release()

for i in range(10):
    t = MyThread()
    t.start()
  • 递归锁:可以acquire多次,每次acquire一次计数器+1,只要计数为0,才能被其他线程抢到
# 递归锁
from threading import Thread,RLock
import time
mutexA = mutexB = RLock()

class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        mutexA.acquire()
        print(‘%s 拿到了A锁‘%self.name)
        mutexB.acquire()
        print(‘%s 拿到了B锁‘%self.name)
        mutexB.release()
        mutexA.release()

    def f2(self):
        mutexB.acquire()
        print(‘%s 拿到了B锁‘ % self.name)
        time.sleep(0.1)
        mutexA.acquire()
        print(‘%s 拿到了A锁‘ % self.name)
        mutexA.release()
        mutexB.release()

for i in range(10):
    t = MyThread()
    t.start()

信号量:可以同时运行多个线程

from threading import Thread,Semaphore,currentThread
import time,random

sm = Semaphore(3)
def task():
    with sm:
        print(‘%s is run‘%currentThread().getName())
        time.sleep(random.randint(1,3))

if __name__ == ‘__main__‘:
    for i in range(10):
        t = Thread(target=task)
        t.start()

Event事件:实现线程同步

  1. event.wait()#等待(可设置等待时间)
  2. event.set()#开始
  3. event.is_set()
from threading import Thread,Event
import time
event = Event()
def student(name):
    print(‘学生 %s正在听课‘%name)
    event.wait()
    print(‘学生%s下课了‘%name)

def teacher(name):
    print(‘老师%s 正在上课‘%name)
    time.sleep(7)
    print(‘老师%s 让学生下课了‘%name)
    event.set()

if __name__ == ‘__main__‘:
    s1 = Thread(target=student,args=(‘wualin‘,))
    s2 = Thread(target=student,args=(‘wxx‘,))
    s3 = Thread(target=student,args=(‘zxx‘,))
    t1 = Thread(target=teacher,args=(‘egon‘,))
    s1.start()
    s2.start()
    s3.start()
    t1.start()

定时器

线程queue

  • 先进先出
import queue
q = queue.Queue(3) #先进先出->队列
q.put(5)
q.put(‘miao‘)
q.put(‘sta‘)

print(q.get())
print(q.get())
print(q.get())

#get 和 put可设置是否阻塞以及阻塞时间

print(q.get(block=True,timeout=3))
  • 后进先出
q = queue.LifoQueue(3)#后进先出->堆栈

q.put(‘fisrt‘)
q.put(2)
q.put(‘miao‘)

print(q.get())
print(q.get())
print(q.get())
  • 优先级队列
import queue
q = queue.PriorityQueue(3)#优先级队列
q.put((10,‘one‘))
q.put((40,‘two‘))
q.put((20,‘three‘))
#数字越小优先级越高
print(q.get())
print(q.get())
print(q.get())

进程池与线程池

  • 池对线程或进程数量进行一个限制
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import os,time,random

def task(name):
    print(‘name:%s pid:%s run‘%(name,os.getpid()))
    time.sleep(random.randint(1,3))


if __name__ == ‘__main__‘:
    pool = ProcessPoolExecutor(4)#进程池
    for i in range(10):
        pool.submit(task,‘egon%s‘%i)#异步调用

    pool.shutdown()#把往进程池提交任务的入口关闭

    print(‘主‘)

异步调用与回调机制

  • 提交任务的两种方式
    • 同步调用:提交完任务后,就在原地等待任务执行完毕,拿到结果再执行下一行代码,程序是串行执行

    • 异步调用

    from concurrent.futures import ThreadPoolExecutor
import time,random

def eat(name):
    print(‘%s is eating‘%name)
    time.sleep(random.randint(2,5))
    res = random.randint(5,10)*‘#‘
    return {‘name‘:name,‘size‘:res}

def count(weith):
    weith = weith.result()#
    name = weith[‘name‘]
    size = len(weith[‘size‘])
    print(‘name:%s eat is %s‘%(name,size))

if __name__ == ‘__main__‘:
    pool = ThreadPoolExecutor(5)
    pool.submit(eat,‘miao‘).add_done_callback(count)#回调机制
    pool.submit(eat,‘car‘).add_done_callback(count)
    pool.submit(eat,‘dog‘).add_done_callback(count)
    pool.submit(eat,‘zhang‘).add_done_callback(count)

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

[Python3] 043 多线程 简介

python中的多线程和多进程编程

多线程 Thread 线程同步 synchronized

多个用户访问同一段代码

在 Python 多处理进程中运行较慢的 OpenCV 代码片段

线程学习知识点总结