Python3使用线程

python学习网 2019-08-29 12:21:14

Python2标准库中提供了两个模块thread和threading支持多线程。
thread有一些缺陷在Python3中弃用,为了兼容性,python3 将 thread 重命名为 "_thread",在Python3中推荐直接使用threading。

创建线程对象

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

参数说明:

group 应该为 None;为了日后扩展 ThreadGroup 类实现而保留。
target 是用于 run() 方法调用的可调用对象。默认是 None,表示不需要调用任何方法。
name 是线程名称。默认情况下,由 "Thread-N" 格式构成一个唯一的名称,其中 N 是小的十进制数。
args 是用于调用目标函数的参数元组。默认是 ()。
kwargs 是用于调用目标函数的关键字参数字典。默认是 {}。
如果 daemon 不是 None,线程将被显式的设置为 守护模式,不管该线程是否是守护模式。如果是 None (默认值),线程将继承当前线程的守护模式属性。

线程对象其中的几个方法

start()开始线程活动。
run() 代表线程活动的方法。
join(timeout=None) 等待,直到线程终结
setDaemon()设置是否为守护线程

一、使用线程有两种方式:函数或者用类来包装线程对象

例子1:使用函数

import random
import threading 
import time

def run(threadName):
    for i in range(5):
        time.sleep(random.random())
        #这里只是演示参数,获取当前线程名可用threading.currentThread().getName()
        print('{} : {}'.format(threadName, i))

t1 = threading.Thread(target=run, args=('thread 1',))
t1.start()
t2 = threading.Thread(target=run, args=('thread 2',))
t2.start()

'''
运行结果:
thread 2 : 0
thread 2 : 1
thread 1 : 0
thread 1 : 1
thread 2 : 2
thread 2 : 3
thread 1 : 2
thread 1 : 3
thread 2 : 4
thread 1 : 4
'''

例子2:使用类(运行结果和例子1类似)

import random
import threading 
import time

class test(threading.Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name
    def run(self):
        for i in range(5):
            time.sleep(random.random())
            print('{} : {}'.format(self.name, i))
        
t1 = test('thread 1')
t1.start()
t2 = test('thread 2')
t2.start()

二、join(timeout=None) 方法

一个进程启动之后,会默认产生一个主线程A,当创建子线程B后,如果不调用B.join(),则主线程A和子线程B会同时执行;
如果调用B.join()则主线程会在调用处等待子线程B执行完后,才继续往下执行。
参数timeout是可选的,代表线程运行的最大时间,如果超过这个时间,不管这个线程有没有执行完毕都会被回收,然后主线程会接着执行。
join在start后才调用。

1、不调用子线程join方法

import random
import threading 
import time

def run():
    name = threading.currentThread().getName()
    print('{} start'.format(name))
    time.sleep(random.random())
    print('{} end'.format(name))

threads = []
for i in range(5):
    threads.append(threading.Thread(target=run))

for th in threads:
    th.start()

print("finished")

'''
运行结果
Thread-1 start
Thread-2 start
Thread-3 start
Thread-4 start
Thread-5 startfinished

Thread-5 end
Thread-3 end
Thread-2 end
Thread-4 end
Thread-1 end
'''

2、调用子线程join方法

import random
import threading 
import time

def run():
    name = threading.currentThread().getName()
    print('{} start'.format(name))
    time.sleep(random.random())
    print('{} end'.format(name))

threads = []
for i in range(5):
    threads.append(threading.Thread(target=run))

for th in threads:
    th.start()

#等待,直到线程终结。
for th in threads:
    th.join()

print("finished")

'''
运行结果
Thread-1 start
Thread-2 start
Thread-3 start
Thread-4 start
Thread-5 start
Thread-3 end
Thread-5 end
Thread-4 end
Thread-1 end
Thread-2 end
finished
'''

三、setDaemon()方法

主线程A中创建子线程B后,如果调用B.setDaemon(),把子线程设置为守护线程。
表示主线程A一旦执行结束,不管子线程B是否执行完成,会全部被终止。
setDaemon和join相反,在start之前设置。

备注:
主线程在其它非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将会被回收,而进程必须保证非守护线程都运行完毕后才能结束。
所以如果存在多个子线程,假设有守护线程B,又有非守护线程C,则主线程会等待非守护线程C执行完,守护线程B如果还没执行完则会被终止。

 

import threading 
import time

def run():
    name = threading.currentThread().getName()
    print('{} start'.format(name))
    time.sleep(2)
    #下面这行代码因为主线程已经执行结束,被终止执行
    print('{} end'.format(name))

print("start")

t = threading.Thread(target=run)
t.setDaemon(True)
t.start()

time.sleep(1)

print("finished")

'''
运行结果
start
Thread-1 start
finished
'''

 

阅读(2307) 评论(0)