学习笔记 python多线程

python多线程

一,线程的实现

1.进程,线程的概念

程序

  • 驱动程序 - 物理硬件
  • 操作系统- 组织硬件,管理,运行应程序
  • 应用程序-qq,微信,吃鸡

应用程序是运行在操作系统上的。

  1. 进程

    操作系统的概念,存储在硬盘上的可执行的二进制数据(可执行文件),在被操作系统运行之后进行资源分配和调度的基本单位。

  2. 线程

    线程是操作系统能够进行运算调度的最小单元,它包含在进程中,是进程的实际运作单位,一个线程指的是进程中一个单一顺序的控制流,一个进程可以并发多个线程。

    任何进程都会默认启动一个线程,我们把该线程成为主线程。

### 2.python操作线程

_thread, threading

  1. 创建线程

    import threading
    
    
    def task():
        """子线程要执行的任务"""
        current_thread = threading.current_thread()
        print('我是线程 %s 我在执行任务' % current_thread.name)
    
    
    if __name__ == '__main__':
        # 创建一个新的线程
        t = threading.Thread(name='abc', target=task)
        # 启动线程
        t.start()
        current_thread = threading.current_thread()
        print('我是线程 %s' % current_thread.name)
  2. 利用多线程来分担耗时任务

    import threading
    import time
    
    
    def task(n):
        """模拟线程执行的耗时任务"""
        t = threading.current_thread()
        print('线程 %s 开始处理任务' % t.name)
        time.sleep(n)
    
    
    if __name__ == '__main__':
        t1 = threading.Thread(target=task, args=(3,))
        t2 = threading.Thread(target=task, args=(3,))
        t3 = threading.Thread(target=task, args=(3,))
        t1.start()
        t2.start()
        t3.start()
        
        
        print('主线程执行完毕!')
  3. 线程同步

    默认,主线程不会等待子线程的任务结束后再结束。

    通过执行子线程的join方法,阻塞主线程,让其等待子线程结束。

    import threading
    import time
    
    
    def task(n):
        """模拟线程执行的耗时任务"""
        t = threading.current_thread()
        print('线程 %s 开始处理任务' % t.name)
        time.sleep(n)
        if not threading.main_thread().isAlive():
            print('领导已经走了!')
    
    
    if __name__ == '__main__':
        s_time = time.time()
        t1 = threading.Thread(target=task, args=(1,))
        t2 = threading.Thread(target=task, args=(2,))
        t3 = threading.Thread(target=task, args=(3,))
        t1.start()
        t2.start()
        t3.start()
    
        t3.join()       # 阻塞 主线程
        # t2.join()
        # t3.join()
        e_time = time.time()
        print('任务总耗时 %s 秒' % (e_time-s_time))
        print('主线程执行完毕!')
  4. 守护线程

    通过设置子线程的daemon=True,将它设置为守护线程,当主线程结束后,即使任务没有完成,它也会被结束。

    import threading
    import time
    
    
    def task(n):
        """模拟线程执行的耗时任务"""
        t = threading.current_thread()
        print('线程 %s 开始处理任务' % t.name)
        time.sleep(n)
        if not threading.main_thread().isAlive():
            print('领导已经走了!')
    
    def task2():
        t = threading.current_thread()
        while True:
            print('我是线程 %s ' % t.name)
            time.sleep(1)
    
    if __name__ == '__main__':
        s_time = time.time()
        t1 = threading.Thread(target=task, args=(1,))
        t2 = threading.Thread(target=task, args=(2,))
        t3 = threading.Thread(target=task2, daemon=True)
        t1.start()
        t2.start()
        t3.start()
    
        t1.join()       # 阻塞 主线程
        t2.join()
        # t3.join()
        e_time = time.time()
        print('任务总耗时 %s 秒' % (e_time-s_time))
        print('主线程执行完毕!')

二, 线程间的资源共享

1. 线程间全局变量共享

import threading
import time

A = 1


def fun():
    print('我是子线程,我要修改全局变量A的值')
    global A
    A = 2


if __name__ == '__main__':
    print('我是主线程,现在A的值是:%s' % A)

    t = threading.Thread(target=fun)
    t.start()
    t.join()
    print('我是主线程,现在A的值是:%s' % A)

2. 线程间资源竞争问题

import threading
import time

A = 0


def task_add():
    global A
    for i in range(1000000):
        A += 1


def task_red():
    global A
    for i in range(1000000):
        A -= 1


if __name__ == '__main__':

    t1 = threading.Thread(target=task_add)
    t2 = threading.Thread(target=task_red)

    t1.start()
    t2.start()

    t1.join()
    t2.join()

    print(A)

高级语言的一条语句,cpu去执行的时候是若干条,即便一个简单的计算:

A += 1

  1. 将A + 1, 存入临时变量

  2. 将临时变量,赋值给A

    x = A + 1
    A = x
    
    初始值 A = 0
    t1: x1 = A + 1    x1 = 1
    t1: A = x1        A = 1
    
    t2: x2 = A - 1    x2 = 0
    t2: A = x2 		  A = 0
    
    初始值:A = 0
    t1: x1 = A + 1    x1 = 1
    t2: x2 = A - 1	  x2 = -1
    t1: A = x1       A = 1
    t2: A = x2        A = -1
    

    3. 互斥锁

    Thread对象提供了一种锁的机制,一个线程在操作一个变量之前需要先获取一把锁 ,然后再操作变量,操作结束后,再释放这把锁。再释放之前,其他的线程都不能操作。

    import threading
    import time
    
    A = 0
    
    
    def task_add(lock):
        lock.acquire()  # 获取锁, 如果锁被其他线程获取了,这时,就会阻塞
        global A        #声明A为全局变量
        for i in range(1000000):
            A += 1
        lock.release()  # 操作完,需要释放
    
    
    def task_red(lock):
        lock.acquire()  # 获取锁,如果锁被其他线程获取了,这时,就会阻塞
        # 。。。
        global A
        for i in range(1000000):
            A -= 1
        lock.release()  # 操作完,你要释放
    
    
    if __name__ == '__main__':
        # 创建一把锁
        lock = threading.Lock()
    
        t1 = threading.Thread(target=task_add, args=(lock, ))
        t2 = threading.Thread(target=task_red, args=(lock, ))
    
        t1.start()
        t2.start()
    
        t1.join()
        t2.join()
    
        print(A)

    4. 队列

    python的queue模块提供了同步的,线程安全的,实现了锁原语的队列类,包括FIFO,LIFO,优先级队列。

    from queue import Queue
    
    
    q = Queue(maxsize=10)   # maxsize 设置队列的大小
    
    q.put(1)                # 往队列中放数据,可以放入任何对象
    q.put((1, ))
    q.put('abc')
    print(q.qsize())        # 输出队列长度
    
    item = q.get()          # 取出一个数据
    q.task_done()           # 给q一个信号,任务执行完毕
    print(item)
    q.get()
    q.get()
    q.task_done()
    q.task_done()
    q.join()                # 阻塞,等待队列任务执行完毕
    print('111111111111')

    5. 生产者消费者模型

    生产者消费者模型实现了:

    1. 生产者与消费者的解耦
    2. 平衡了生产力与消费力
      在这里插入图片描述

三,线程池

为了更好地利用多线程,出现了池的概念。所有的子线程放到一个池中,由池对子线程进行调度和管理,提高系统资源的利用率。

1.线程池的简单实现
import os
import time
import random
import threading
from queue import Queue


class MyPool:
    def __init__(self, size):
        if size is None:
            size = os.cpu_count() or 1

        if size < 1:
            raise ValueError('Number of thread must be at lease 1')
        self.size = size  # 线程数量
        self.queue = Queue()   # 任务队列

        # 创建线程
        for i in range(self.size):
            t = threading.Thread(target=self.job, daemon=True)
            t.start()

    def job(self):
        # 线程任务
        while True:
            # (func, args, kwargs)
            # 没有任务堵在这里
            func, args, kwargs = self.queue.get()     # 获取任务
            func(*args, **kwargs)                     # 执行任务
            self.queue.task_done()                    # 执行完毕,通知队列

    # 添加任务
    def apply_async(self, func, args=(), kwargs=None):
        if kwargs is None:
            kwargs = {}
        self.queue.put((func, args, kwargs))

    # 阻塞主线程,知道任务完成
    def join(self):
        self.queue.join()

def task1():
    print('我是线程 %s 我开始执行task1' % threading.current_thread().name)
    time.sleep(random.randint(1, 3))
    print('我是线程 %s 我的任务执行完毕' % threading.current_thread().name)


def task2(*args, **kwargs):
    print('我是线程 %s 我开始执行task2' % threading.current_thread().name)
    print('我接收到的参数是:', args, '|', kwargs)
    time.sleep(random.randint(1, 3))
    print('我时线程 %s 我的任务执行完毕' % threading.current_thread().name)


if __name__ == '__main__':
    pool = MyPool(5)

    for i in range(10):
        if i % 2 == 0:
            pool.apply_async(task1)
        else:
            pool.apply_async(task2, args=(1, 2), kwargs={'a': 1, 'b': 3})


    print('任务提交完成')
    pool.join()
    print('任务执行完毕')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值