多线程编程之线程创建

193 阅读3分钟

创建一个可执行的线程需要具备线程对象和线程体这2个要素

线程对象:即threading模块Thread线程类或其子类所创建的对象

线程体:即执行函数

线程体主要有以下两种方式:

(1)自定义函数作为线程体

(2)继承Thread线程类重写run()方法,run()方法作为线程体

1 自定义函数作为线程体

线程创建语法如下:

threading.Thread(target=None, name=None, args=())

target参数是线程体,自定义函数可以作为线程体。name参数可以设置线程名,如果省略,python解释器会为其分配一个名字。args是为自定义函数提供参数,它是一个元组类型。

example:

import threading
import time
​
​
def thread_body(func):
    t = threading.current_thread()
    for num in range(5):
        print(f'第{num}次执行线程{t.name}')
        time.sleep(1)
    print(f'{func}环境的线程{t.name}执行完成!')
​
​
def main():
    t1 = threading.Thread(target=thread_body, name='test_thread_01', args=('测试', ))
    t1.start()
    t2 = threading.Thread(target=thread_body, name='test_thread_02', args=('正式',))
    t2.start()
​
​
if __name__ == '__main__':
    main()

result:

第0次执行线程test_thread_01
第0次执行线程test_thread_02
第1次执行线程test_thread_02第1次执行线程test_thread_01
​
第2次执行线程test_thread_02
第2次执行线程test_thread_01
第3次执行线程test_thread_01第3次执行线程test_thread_02
​
第4次执行线程test_thread_02第4次执行线程test_thread_01
​
正式环境的线程test_thread_02执行完成!测试环境的线程test_thread_01执行完成!

注:

(1)这里解释一下,因为多线程会存在资源竞争的问题,所以导致输出的内容换行会有问题,且每次执行输出换行都 不一样。这个需要加互斥锁进行解决

(2)从结果来看,两个线程交替进行会有一种两个线程同时进行的错觉。但实际上一台只有一个CPU的电脑在某个特定时刻有且只有一个线程在运行。上述运行结果的产生是我们在程序中通过让当前程序休眠(就是代码中的time.sleep(1))将CPU资源让给其他线程执行的结果。假使我们去掉了time.sleep(1),效果如下:

import threading
import time
​
​
def thread_body(func):
    t = threading.current_thread()
    for num in range(5):
        print(f'第{num}次执行线程{t.name}')
        # time.sleep(1)
    print(f'{func}环境的线程{t.name}执行完成!')
​
​
def main():
    t1 = threading.Thread(target=thread_body, name='test_thread_01', args=('测试', ))
    t1.start()
    t2 = threading.Thread(target=thread_body, name='test_thread_02', args=('正式',))
    t2.start()
​
​
if __name__ == '__main__':
    main()

result:

第0次执行线程test_thread_01
第1次执行线程test_thread_01
第2次执行线程test_thread_01
第3次执行线程test_thread_01
第4次执行线程test_thread_01
测试环境的线程test_thread_01执行完成!
第0次执行线程test_thread_02
第1次执行线程test_thread_02
第2次执行线程test_thread_02
第3次执行线程test_thread_02
第4次执行线程test_thread_02
正式环境的线程test_thread_02执行完成!

其结果完全就是阻塞式的按顺序执行了,即先知先线程1,线程1执行完毕才会执行第二个线程。

2 继承Thread线程类实现线程体

另外一种实现线程体的方式是,创建一个Thread类,并重写run()方法,

example:

import threading
import time
​
​
class MyThread(threading.Thread):
    def __init__(self, name=None):
        super().__init__(name=None)
​
    def run(self):
        t = threading.current_thread()
        for num in range(5):
            print(f'第{num}次执行线程{t.name}')
            time.sleep(1)
        print(f'线程{t.name}执行完成!')
​
​
def main():
    t1 = MyThread()
    t1.start()
    t2 = MyThread(name='MyThread')
    t2.start()
​
​
if __name__ == '__main__':
    main()

result:

第0次执行线程Thread-1
第0次执行线程Thread-2
第1次执行线程Thread-2第1次执行线程Thread-1
​
第2次执行线程Thread-2
第2次执行线程Thread-1
第3次执行线程Thread-2第3次执行线程Thread-1
​
第4次执行线程Thread-2
第4次执行线程Thread-1
线程Thread-1执行完成!线程Thread-2执行完成!