Fork me on GitHub

Python多线程(一)

1
这是崔斯特的第六十一篇原创文章

记录自己对多线程的理解 (๑• . •๑)

线程与影分身

多线程就是鸣人的影分身之术,可能不大恰当,但是非常容易理解。

平时一个鸣人会一个人,但是遇到强敌时,他会使用影分身之术,召唤自己的兄弟来帮助他一起来战斗。这样,他就从一个人战斗变成多个人战斗。

多线程也是这样,平时一个线程去做某件事,当使用多线程后,就会有很多个线程按照命令去做事,就像影分身一样。

Python使用

鸣人和使用需要先结印

Python 中需要先调用,让我们看一个简单的例子:

1
2
3
4
5
6
7
8
9
import threading
def shadow(num):
print('产生了第{}个分身...'.format(num))
for i in range(1, 6):
t = threading.Thread(target=shadow, args=(i,))
t.start()
t.join()

Output

1
2
3
4
5
产生了第1个分身...
产生了第2个分身...
产生了第3个分身...
产生了第4个分身...
产生了第5个分身...

可以看出用法非常简单,只需要先导入threading模块,然后实例化一个线程对象,注意args是元祖

t = threading.Thread(target=shadow, args=(i,))

线程被创建之后并不会马上运行,需要手动调用 start()join() 让调用它的线程一直等待直到执行结束:

1
2
t.start()
t.join()

查看线程名字

上述例子中,我们只知道产生了多个线程,但还是并不知道具体是哪个线程,如果某个线程出错了,我们没法去追踪,所以我们可以给线程加上名字。

1
2
3
4
5
6
7
8
9
import threading
def shadow(num):
print('{}产生了第{}个分身...'.format(threading.currentThread().getName(), num))
for i in range(1, 6):
t = threading.Thread(target=shadow, args=(i,), name='第{}个鸣人'.format(i))
t.start()
t.join()

Out:

1
2
3
4
5
第1个鸣人产生了第1个分身...
第2个鸣人产生了第2个分身...
第3个鸣人产生了第3个分身...
第4个鸣人产生了第4个分身...
第5个鸣人产生了第5个分身...

当然,你可以这样

1
2
3
4
5
6
7
8
9
10
11
import threading
def shadow(num):
print('{}产生了第{}个分身...'.format(threading.currentThread().getName(), num))
for i in range(1, 6):
t = threading.Thread(target=shadow, args=(i,))
t.start()
t.join()
print(threading.currentThread().getName())

Out

1
2
3
4
5
6
Thread-1产生了第1个分身...
Thread-2产生了第2个分身...
Thread-3产生了第3个分身...
Thread-4产生了第4个分身...
Thread-5产生了第5个分身...
MainThread

你可以看到在所有创建的线程结束后,我们打印当前线程名字,就是主线程MainThread

什么时候使用join

刚开始学多线程时,有个问题困扰了我很久,就是什么时候使用join()

缕一缕步骤:

  1. 主线程中创建子线程t
  2. 开始线程t.star()
  3. 调用t.join()
  4. 阻塞:等待子线程t结束后,再执行接下来的任务

也就是说使用了join()后会阻塞当前的线程,只有这个线程执行完毕后才会接着走。要是一直不结束呢?你可以加上超时时间,如t.join(timeout=10)

后续

鸣人使用影分身后,产生了A、B、C三个小鸣人,鸣人可以使用join()方法,让B在A耗尽查克拉之后再进行攻击,如果没有使用join(),那么就会是这样的场景,大家一起上

这个时候如果鸣人命令A、B同时去写家庭作业,那么可能会产生什么情况呢?A先写还是B先写,大家可以想想。

下一期会说说