Python --多线程

目录

1, 什么是进程

2, 什么是线程

3, 什么是GIL

3-1, GIL设置流程

4, threading模块

4-1, threading模块 VS thread模块

4-2, Thread类的方法

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

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

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

5, queue模块

5-1, queue模块方法

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


1, 什么是进程

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

2, 什么是线程

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

3, 什么是GIL

GIL叫着全局解释锁,对python解释器的的访问由GIL来控制,通过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, Thread类的方法

strat():线程执行

In [6]: 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)
   ...:

In [7]: def func():
   ...:     print("haha")
   ...:

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

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

In [10]:

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=None):等待线程结束,若设置timeout, 则等待timeout后线程结束

getName():获取线程的名称,该方法已过期,获取线程的名称使用"线程.name"方法获取

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

setName():设置线程的名称, 该方法以过期,通过t.name="线程名字"来给线程重命名

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

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

isAlive():判断线程是否存活,是返回True,否则返回False, 该方法已过期,使用新方法:

"t.is_alive()"

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

isDeamon():判断线程是否是守护线程,是则返回True,否则返回False,该方法已过期,使用新方法"t.daemon"

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

setDeamon(True):设置线程为守护线程

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

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

4-3, 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

4-3, 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

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

5, queue模块

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

5-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

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

你可能感兴趣的:(python,开发语言,python)