1.多线程类似于使用计算机的一个核心执行不同的任务,好处如下:
- 使用线程可以把需要使用大量时间的计算任务放到后台去处理
- 减少资源占用,加快程序的运行速度
2.操作线程的模块threading,相对于Python既有的多线程模块,threading重写了部分API模块,对thread进行了二次封装,大大提高了执行效率,并且重写了更为方便的API来处理线程。
3.threading的使用
threading.Thread:这个类可以可以被子类以有限的样式继承。有两种具体的方法:
-
(1)方法1:
- 传递可调用的对象:
t = threading.Thread(target=None,args=(),kwargs=None) target:是可以被run()方法调用的对象,默认为None。 args:供target调用的元组元素,默认为() kwargs:供target调用的关键字元素,默认为{}
- 示例:
import time import threading def func1(str): print("func1 start!",time.ctime()) print(str) time.sleep(4) print("func1 end!",time.ctime()) def func2(str): print("func2 start!",time.ctime()) print(str) time.sleep(3) print("func2 end!",time.ctime()) def main(): t1 = threading.Thread(target=func1,args=("情人节",)) t1.start() #t1和t2给参数的方法均可,但是args只有一个参数时必须有 , 否则报错 t2 = threading.Thread(func2("快乐")) t2.start() if __name__ == "__main__": main() Output: func1 start! Wed Aug 7 11:01:30 2019 func2 start! Wed Aug 7 11:01:30 2019 情人节 快乐 func2 end! Wed Aug 7 11:01:33 2019 func1 end! Wed Aug 7 11:01:34 2019
-
(2)方法2:
import threading import time count = 0 class MyThread(threading.Thread): def __init__(self): super(MyThread,self).__init__() #threading.Thread.__init__(self) 也可以 #重写run方法 def run(self): global count for i in range(6): #防止程序执行太快无法看到过程 time.sleep(0.5) #打印线程名称 print(self.getName(), count) count += 1 if __name__ == '__main__': threadList = [] for i in range(2): threadList.append(MyThread()) for single_thread in threadList: single_thread.start() Output: Thread-2 0 Thread-1 0 Thread-2 2 Thread-1 2 Thread-2 4 Thread-1 5 Thread-1 6 Thread-2 6 Thread-2 8 Thread-1 8 Thread-2 10 Thread-1 10 #可以看出,程序在运行过程中,两个线程同时对一个数进行操作,并将结果打印。 #但是出现应该逐次打印的数据变成了两个相同的数值,我们可以用threading中的Lock类解决。
- 利用Lock类解决打印数值相同的问题:Lock类作用是对当前运行中的线程进行锁定,只有当前的线程被释放后,后序的线程才能继续操作。
import threading import time count = 0 #添加Lock对象 lock = threading.Lock() class MyThread(threading.Thread): def __init__(self): super(MyThread,self).__init__() self.lock = lock #重写run方法 def run(self): global count #确定对象被锁定的标志 self.lock.acquire() for i in range(6): # count += 1 time.sleep(0.5) print(self.getName(), count) count += 1 #释放当前对象 self.lock.release() if __name__ == '__main__': threadList = [] for i in range(2): threadList.append(MyThread()) for single_thread in threadList: single_thread.start() Output: Thread-1 0 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4 Thread-1 5 Thread-2 6 Thread-2 7 Thread-2 8 Thread-2 9 Thread-2 10 Thread-2 11 #可以看出,Thread-1结束后再执行Thread-2
- threading中的join类:作用是阻止全部的线程继续运行,知道被调用的线程执行完毕或者超时。
import threading import time def join_wait(): print("start waiting:", time.ctime()) time.sleep(3) print("stop waiting:", time.ctime()) thread_1 = threading.Thread(target=join_wait) thread_1.start() # 启动线程 print("start join",time.ctime()) thread_1.join() #将主线程阻塞,知道thread_1结束再往下执行 print("end join",time.ctime()) Output: start waiting: Wed Aug 7 12:52:48 2019 start join Wed Aug 7 12:52:48 2019 end join Wed Aug 7 12:52:48 2019 stop waiting: Wed Aug 7 12:52:51 2019
-
线程中的一些方法:
- isAlive():查看线程是否是活动的,返回值是bool类型。
#利用帮助函数查询 help(threading.Thread.is_alive) Output: is_alive(self) Return whether the thread is alive. This method returns True just before the run() method start until just after the run() method terminates. The module function enumerate() returns a list of all alive threads.
1.即在run方法执行开始到结束时,认为线程是活动的。
2.模块函数enumerate()返回所有活动的线程。
- getName():获取线程名称,样式是Thread-No
- setName():设置线程名称
import threading t = threading.Thread() t.setName("T1") print(t.getName()) Output:T1
- run():代表线程活动的方法
可以在子类中重写这个方法,标准的run()方法调用回调对象传递给构造函数的target元素。 - setDaemon(daemonic):将线程设置为守护线程,说明该线程不重要,在进程退出的时候不用等待这个线程退出。
import time import threading def func(): print("start func") time.sleep(2) print("end func") print("start main thread") t = threading.Thread(target=func) t.setDaemon(True) #将线程设置为守护线程 t.start() time.sleep(1) print("end main thread") Output: start main thread start func end main thread #由结果,线程t设置为守护线程,未执行完就退出了
有任何问题可以留言小g