Python多线程的使用

在这里插入图片描述

往期推荐

Python线程池的使用
Python多线程的安全问题
Lock与RLock的区别

B站同名【有温度的算法】已经上线
想观看视频讲解的同学
点击此处直达B站

单线程

我们知道进程是资源分配的单位,线程是处理机调度的单位。下文就以简明的例子带大家理解线程,并使用Python实现多线程。

比如在飞车程序中,我们在玩游戏的同时,还可以听到游戏为我们配置的背景音乐。在这个例子中启动飞车程序就是一个进程,玩游戏和听音乐是两个线程。

在最早的计算机中,操作系统处理问题是单任务的,要玩游戏和听音乐,就一定要顺序进行,不能并发。我们假设玩游戏需要3秒,听音乐需要1秒。

def music(music_name):
    for i in range(2):
        print('正在听{}'.format(music_name))
        sleep(1)
        print('music over')

def game(game_name):
    for i in range(2):
        print('正在玩{}'.format(game_name))
        sleep(3)
        print('game over')

if __name__ == '__main__':
    music('稻香')
    game('飞车')
    print('主线程结束')

我先听了一首《稻香》,通过for循环控制音乐播放两次,每首音乐播放需要1秒,sleep()来控制音乐播放的时长,接着又玩了两把飞车,最后关闭了程序。


----输出----
正在听稻香
music over
正在听稻香
music over
正在玩飞车
game over
正在玩飞车
game over
主线程结束

多线程

随着技术的不断进步,操作系统就进入了多任务时代。在单核架构中的多线程是以极短的时间间隔交替执行任务,让人感觉它们在同时执行一样。以“吃着火锅唱着歌”举例,若是单线程则是先吃火锅,直到吃完后再唱歌,但是多线程的话我们可以吃一口唱一句,达到“吃着火锅唱着歌”的效果。

Python提供了threading模块来实现多线程 。我们对上面的例子进行改造,实现在听音乐的同时玩飞车。在此之前先为大家介绍一下线程的相关概念。

主线程:当一个程序启动时,就有一个进程被操作系统(OS)创建,与此同时一个线程也立刻运行,该线程通常叫做程序的主线程(Main Thread)。因为它是程序开始时就执行的,如果你需要再创建线程,那么创建的线程就是这个主线程的子线程。

子线程:使用threading、ThreadPoolExecutor创建的线性均为子线程。

主线程的重要性体现在两方面:1.是产生其他子线程的线程;2.通常它必须最后完成执行,比如执行各种关闭动作。


from time import sleep
import threading

def music(music_name):
    for i in range(2):
        print('正在听{}'.format(music_name))
        sleep(1)
        print('music over')

def game(game_name):
    for i in range(2):
        print('正在玩{}'.format(game_name))
        sleep(3)
        print('game over')

threads = []
t1 = threading.Thread(target=music,args=('稻香',))
threads.append(t1)
t2 = threading.Thread(target=game,args=('飞车',))
threads.append(t2)

if __name__ == '__main__':
    for t in threads:
        t.setDaemon(True)
        t.start()
    print('主线程运行结束')

首先导入模块,使用threading.Thread()方法创建线程,然后在这个方法中使用target指定music任务,args方法对music进行传参,将听歌线程定义为t1,接着以同样的方式创建线程t2,并将他们一起放到threads列表中。

然后通过for遍历threads,start()方法为启动线程的命令。setDaemon(True)将线程声明为守护主线程,作用是子线程启动后,主线程也继续执行下去,当主线程执行完’主线程运行结束’后,它不会等待子线程运行结束,而是自己直接结束,同时子线程也一同结束。

----输出----
正在听稻香
正在玩飞车
主线程运行结

我们可以看到这并不符合我们的要求,子线程(muisc 、game )和主线程(print(‘主线程运行结束’))都是同一时间启动,但由于主线程执行完结束,所以导致子线程也终止。所以我们使用join()方法,守护子线程。

from time import sleep
import threading

def music(music_name):
    for i in range(2):
        print('正在听{}'.format(music_name))
        sleep(1)
        print('music over')

def game(game_name):
    for i in range(2):
        print('正在玩{}'.format(game_name))
        sleep(3)
        print('game over')

threads = []
t1 = threading.Thread(target=music,args=('稻香',))
threads.append(t1)
t2 = threading.Thread(target=game,args=('飞车',))
threads.append(t2)

if __name__ == '__main__':
    for t in threads:
        t.start()

    for t in threads:
        t.join()
    print('主线程运行结束')

join()的作用是在子线程完成运行之前,主线程将一直被阻塞。

----输出----
正在听稻香
正在玩飞车
music over
正在听稻香
music over
game over
正在玩飞车
game over
主线程运行结束

如果不使用setDaemon与join,那么最后的结果是主线程与子线程同时运行,直到所有线程都运行结束,程序才会结束。

----不使用setDaemon与join的输出----
正在听稻香
正在玩飞车
主线程运行结束
music over
正在听稻香
music over
game over
正在玩飞车
game over

以上为Python使用多线程的基本框架,获取本章代码集合,可关注公众号【有温度的算法】,在后台回复【多线程】即可获取。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值