手把手带你理解python3多线程【1】

写在最前面:python3使用两种模块引入线程的概念

  • _thread
  • threading(推荐使用)

由于在python2中使用thread模块,而在python3中该模块已经被废弃,使用_thread来兼容,今天的例子都是基于python3的threading

 

首先,我们来看一下没有用线程的例子:

import time
import threading
from time import ctime,sleep


def First():
    for i in range(3):
        print("The First start at %s" % ctime())
        sleep(1)


def Second():
    for i in range(3):
        print("The Second start at %s" % ctime())
        sleep(5)


if __name__ == '__main__':
    First()
    Second()
    print("all over %s" %ctime())
The First start at Mon Oct 29 16:41:26 2018
The First start at Mon Oct 29 16:41:27 2018
The First start at Mon Oct 29 16:41:28 2018
The Second start at Mon Oct 29 16:41:29 2018
The Second start at Mon Oct 29 16:41:34 2018
The Second start at Mon Oct 29 16:41:39 2018
Exception ignored in: <module 'threading' from 'F:\\leetcode\\threading.py'>
AttributeError: module 'threading' has no attribute '_shutdown'
all over Mon Oct 29 16:41:44 2018

Process finished with exit code 0

一个小插曲,出现了一个报错,这是因为我把这个py文件命名为threading.py和线程本身的模块名重复了

上面的例子很好理解,程序很听话的按照我们调用函数的顺序执行了First,Second,那么有没有办法同时执行呢?

可以,通过threading线程

为了更好的理解threading,我们在启用线程的时候加入参数

import time
import threading
from time import ctime,sleep


def First(name):
    for i in range(3):
        print("The %s start at %s" % (name, ctime()))
        sleep(1)


def Second(name):
    for i in range(3):
        print("The %s start at %s" % (name, ctime()))
        sleep(5)

threads = []
t1 = threading.Thread(target=First,args=(u'First',))
threads.append(t1)
t2 = threading.Thread(target=Second,args=(u'Second',))
threads.append(t2)

if __name__ == '__main__':
    for t in threads:
        t.setDaemon(True)
        t.start()
    print("all over %s" %ctime())

这时的输出结果是:

The First start at Mon Oct 29 17:03:44 2018
The Second start at Mon Oct 29 17:03:44 2018
all over Mon Oct 29 17:03:44 2018

Process finished with exit code 0

大家有没有发现,我们明明在子线程中写了循环遍历,为什么输出只有一个?

这里我们讲一讲setDaemon

setDaemom默认false,当我们置为True时,子线程为守护线程,主线程一旦执行结束,则全部子线程被强制终止。所以当for循环结束,所有的子线程被起来后,主线程也结束,此时子线程强制结束。

那如何使得子线程继续执行呢?

import time
import threading
from time import ctime,sleep


def First(name):
    for i in range(3):
        print("The %s start at %s" % (name, ctime()))
        sleep(1)


def Second(name):
    for i in range(3):
        print("The %s start at %s" % (name, ctime()))
        sleep(5)

threads = []
t1 = threading.Thread(target=First,args=(u'First',))
threads.append(t1)
t2 = threading.Thread(target=Second,args=(u'Second',))
threads.append(t2)

if __name__ == '__main__':
    for t in threads:
        #t.setDaemon(True)
        t.start()
    print("all over %s" %ctime())

此时的结果如下:

The First start at Mon Oct 29 17:08:57 2018
The Second start at Mon Oct 29 17:08:57 2018
all over Mon Oct 29 17:08:57 2018
The First start at Mon Oct 29 17:08:58 2018
The First start at Mon Oct 29 17:08:59 2018
The Second start at Mon Oct 29 17:09:02 2018
The Second start at Mon Oct 29 17:09:07 2018

Process finished with exit code 0

大家可以看到,主线程结束后,子线程继续执行

 

那么有没有办法使得主线程等待子线程执行完毕再执行呢?

可以,使用join()

import time
import threading
from time import ctime,sleep


def First(name):
    for i in range(3):
        print("The %s start at %s" % (name, ctime()))
        sleep(1)


def Second(name):
    for i in range(3):
        print("The %s start at %s" % (name, ctime()))
        sleep(5)

threads = []
t1 = threading.Thread(target=First,args=(u'First',))
threads.append(t1)
t2 = threading.Thread(target=Second,args=(u'Second',))
threads.append(t2)

if __name__ == '__main__':
    for t in threads:
        t.setDaemon(True)
        t.start()
    t.join()
    print("all over %s" %ctime())

这时我们可以清晰的看到

The First start at Mon Oct 29 17:11:14 2018
The Second start at Mon Oct 29 17:11:14 2018
The First start at Mon Oct 29 17:11:15 2018
The First start at Mon Oct 29 17:11:16 2018
The Second start at Mon Oct 29 17:11:19 2018
The Second start at Mon Oct 29 17:11:24 2018
all over Mon Oct 29 17:11:29 2018

Process finished with exit code 0

当所有子线程都结束之后,主线程才开始执行,此时的子线程不需要守护,因为我们使用join()保证了只有当子线程全部结束,主线程才会执行

那如果我们把join()加入for循环里面呢?

The First start at Mon Oct 29 17:29:36 2018
The First start at Mon Oct 29 17:29:37 2018
The First start at Mon Oct 29 17:29:38 2018
The Second start at Mon Oct 29 17:29:39 2018
The Second start at Mon Oct 29 17:29:44 2018
The Second start at Mon Oct 29 17:29:49 2018
all over Mon Oct 29 17:29:54 2018

Process finished with exit code 0

此时,当第一个子线程还没结束时,主线程无法再次调用for循环起第二个子线程,只能等待第一个子线程结束后,开始第二个子线程。

 

今天头疼,先讲到这儿,最优化和C++算法作业还没写,难受

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值