Python --多线程

目录

1, 进程

2, 线程

3, GIL

3-1, GIL设置流程

4, threading模块

4-1, threading模块 VS thread模块

4-2, threading.Thread类的方法

5, 创建多线程

5-1, Thread(target=函数名, args=(...))创建多线程

5-2, Thread(target=类实例, args=(...))创建多线程

5-3, Thread(target=Thread子类实例, args=(...))创建多线程

6, queue模块

6-1, queue模块方法

6-2,线程共享数据举例


1, 进程

进程是程序的一次执行,每个进程都有自己独立的地址空间,内存,数据栈以及记录其运行轨迹的辅助数据

2, 线程

一个进程中可以有多个线程,一个进程中多个线程共享相同的运行环境,数据空间

3, GIL

GIL叫着全局解释锁GIL控制着python解释器的访问,通过GIL保证了同一时刻,只能有一个python线程运行

3-1, GIL设置流程

1, 设置GIL

2, 切换到一个线程中去运行指定数量的字节码,线程主动让出控制(处于等待状态时,线程主动让出控制)

3, 把步骤2的线程设置为挂起状态

4, 解锁GIL

5, 重复以上步骤

4, threading模块

4-1, threading模块 VS thread模块

thread模块不支持守护线程,当主线程退出时,所有的子程序都会被强制退出

threading模块支持守护线程,主线程会等待所有子线程完成后,才会退出;

threading模块,若存在守护线程,则主线程不用等待守护线程退出

4-2, threading.Thread类的方法

通过线程名.strat(), 线程执行

In [8]: t = MyThread(func, ())

# 启动线程
In [9]: t.start()
haha

通过run(), 定义线程的功能函数(一般会被子类重写)

In [6]: class MyThread(threading.Thread):
   ...:     def __init__(self, func, args):
   ...:         super(MyThread, self).__init__()
   ...:         self.func = func
   ...:         self.args = args
            # 定义线程的功能函数
            # 在继承threading.Thread时,需要重新定义run函数
   ...:     def run(self):
   ...:         self.func(*self.args)

通过join(timeout), 不设置timeout表示, 等待线程结束,若设置timeout, 则等待timeout后线程结束

通过线程.name, 方法获取线程名称

In [11]: t.name
Out[11]: 'Thread-1'

通过t.name="线程名字", 命名线程

# 设置线程t的名称为:Thread1_1
In [22]: t.name = 'thread1_1'

In [23]: t.name
Out[23]: 'thread1_1'

通过线程名.is_alive(), 判断线程是否存活,是返回True,否则返回False

In [14]: t.is_alive()
Out[14]: False

通过t.daemon, 判断线程是否是守护线程,是则返回True,否则返回False

In [16]: t.daemon
Out[16]: False

通过setDeamon(True), 设置线程为守护线程

# 设置线程t为守护线程,需要在线程启动前进行设置
In [20]: t.setDaemon(True)
<ipython-input-20-e5fbb5aed3c8>:1: DeprecationWarning: setDaemon() is deprecated, set the daemon attribute instead
  t.setDaemon(True)

In [21]: t.daemon
Out[21]: True

5, 创建多线程

5-1, Thread(target=函数名, args=(...))创建多线程

#! /usr/bin/env python
# -*- coding:utf-8 -*-

import threading
from time import ctime, sleep


def loop(nloop, nsec):
    print("start loop %s at %s" % (nloop, ctime()))
    sleep(nsec)
    print("loop %s done at: %s" % (nloop, ctime()))


def main():
    print("strating at:", ctime())
    loops = [4, 2]
    nloops = range(len(loops))
    thread_list = []

    # 创建线程池
    for i in nloops:
        # target传入目标函数名,args为目标函数参数
        # 注意:若目标函数没有参数,也需要传入一个空元组
        t = threading.Thread(target=loop, args=(i, loops[i]))
        thread_list.append(t)

    # 通过start()方法启动线程池
    for t in thread_list:
        t.start()

    # 通过join()方法等待线程池结束
    # join()方法是一旦线程启动后,就会一直运行,直到线程的函数结束,退出为止
    # 所以join()方法可以不用显示调用
    for t in thread_list:
        t.join()

    print("all done at:", ctime())


if __name__ == "__main__":
    main()


# 输出结果:
strating at: Tue Aug 22 12:19:06 2023
start loop 0 at Tue Aug 22 12:19:06 2023
start loop 1 at Tue Aug 22 12:19:06 2023
loop 1 done at: Tue Aug 22 12:19:08 2023
loop 0 done at: Tue Aug 22 12:19:10 2023
all done at: Tue Aug 22 12:19:10 2023

5-2, Thread(target=类实例, args=(...))创建多线程

#! /usr/bin/env python
# -*- coding:utf-8 -*-

import threading
from time import ctime, sleep


class ThreadFun(object):
    def __init__(self, func, args):
        self.func = func
        self.args = args

    def __call__(self):
        '''该方法的作用是类的实例像函数一样调用'''
        self.func(*self.args)


def loop(nloop, nsec):
    print("start loop %s at %s" % (nloop, ctime()))
    sleep(nsec)
    print("loop %s done at: %s" % (nloop, ctime()))


def main():
    print("strating at:", ctime())
    loops = [4, 2]
    nloops = range(len(loops))
    thread_list = []

    # 创建线程池
    for i in nloops:
        # target传入类实例,这里没有args参数
        t = threading.Thread(target=ThreadFun(loop, (i, loops[i])))
        thread_list.append(t)

    # 通过start()方法启动线程池
    for t in thread_list:
        t.start()

    for t in thread_list:
        t.join()

    print("all done at:", ctime())


if __name__ == "__main__":
    main()

# 输出结果
strating at: Wed Aug 23 11:51:02 2023
start loop 0 at Wed Aug 23 11:51:02 2023
start loop 1 at Wed Aug 23 11:51:02 2023
loop 1 done at: Wed Aug 23 11:51:04 2023
loop 0 done at: Wed Aug 23 11:51:06 2023
all done at: Wed Aug 23 11:51:06 2023

5-3, Thread(target=Thread子类实例, args=(...))创建多线程

#! /usr/bin/env python
# -*- coding:utf-8 -*-

import threading
from time import ctime, sleep


class MyThread(threading.Thread):
    def __init__(self, func, args):
        super(MyThread, self).__init__()
        self.func = func
        self.args = args
    
    def run(self):
        """定义线程运行的功能函数"""
        self.func(*self.args)


def loop(nloop, nsec):
    print("start loop %s at %s" % (nloop, ctime()))
    sleep(nsec)
    print("loop %s done at: %s" % (nloop, ctime()))


def main():
    print("strating at:", ctime())
    loops = [4, 2]
    nloops = range(len(loops))
    thread_list = []

    # 创建线程池
    for i in nloops:
        # 注意:这里没有target参数,直接是threading.Thread子类的实例
        t = MyThread(loop, (i, loops[i]))
        thread_list.append(t)

    # 通过start()方法启动线程池
    for t in thread_list:
        t.start()

    for t in thread_list:
        t.join()

    print("all done at:", ctime())


if __name__ == "__main__":
    main()

6, queue模块

通过queue模块能让线程与线程之间共享数据

6-1, queue模块方法

 通过QUEUE(), 创建一个QUEUE对象, QUEUE中的对象是先进先出

# 创建大小为32的QUEUE对象
In [1]: from queue import Queue

In [2]: q = Queue(32)

通过q.put(item, timeout), 对象item放入到queue中, timeout为超时时间

In [2]: q = Queue(32)

In [3]: q.put('xxxx')

通过q.get(timeout), 获取QUEUE中的对象, timeout为超时时间

In [6]: q.get()
Out[6]: 'xxxx'

通过q.full(), 若QUEUE队列已满,则返回True,否则返回False

In [8]: q.full()
Out[8]: False

通过q.empty(), 若QUEUE队列为空,则返回True,否则返回False

In [7]: q.empty()
Out[7]: False

通过q.qsize(), 返回当前QUEUE队列的大小

In [9]: q.qsize()
Out[9]: 1

6-2,线程共享数据举例

from threading import Thread
from queue import Queue


class MyThread(Thread):
    """自定义多线程类"""
    def __init__(self, func, args):
        super(MyThread, self).__init__()
        self.func = func
        self.args = args

    def run(self):
        self.func(*self.args)


def read_queue(q):
    """从QUEUE中取出一个对象"""
    print('get object from q:', q.get())
    print("now qsize:", q.qsize())


def write_queue(q, item):
    """写入一个对象到QUEUE中"""
    print('write object in q:')
    # 将item放入Queue中
    q.put(item)
    print("now qsize:", q.qsize())


if __name__ == "__main__":
    func_list = [write_queue, read_queue]
    nfuncs = range(len(func_list))
    q = Queue(32)
    thread_list = []

    for i in range(5):
        t = MyThread(write_queue, (q, ('object_%s' % i)))
        thread_list.append(t)

    for i in range(3):
        t = MyThread(read_queue, (q, ))
        thread_list.append(t)

    for i in range(len(thread_list)):
        thread_list[i].start()

    for i in nfuncs:
        thread_list[i].join()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值