###1、多线程的理解
多进程和多线程都可以执行多个任务,线程是进程的一部分。线程的特点是线程之间可以共享内存和变量,资源消耗少,缺点是线程之间的同步和加锁比较麻烦。
一般线程的运行逻辑,如图:
* 新建:使用线程的第一步就是创建线程,创建后的线程只是进入可执行的状态,也就是Runnable
* Runnable:进入此状态的线程还并未开始运行,一旦CPU分配时间片给这个线程后,该线程才正式的开始运行
* Running:线程正式开始运行,在运行过程中线程可能会进入阻塞的状态,即Blocked
* Blocked:在该状态下,线程暂停运行,解除阻塞后,线程会进入Runnable状态,等待CPU再次分配时间片给它
* 结束:线程方法执行完毕或者因为异常终止返回
其中最复杂的是线程从Running进入Blocked状态,通常有三种情况:
* 睡眠:线程主动调用**sleep()或join()**方法后.
* 等待:线程中调用**wait()方法,此时需要有其他线程通过notify()**方法来唤醒
* 同步:线程中获取线程锁,但是因为资源已经被其他线程占用时.
###2、Python多线程创建
在Python中,同样可以实现多线程,有两个标准模块thread和threading,不过我们主要使用更高级的threading模块。
#####实例:
import threading import time #定义线程需要做的内容,写在函数里面 def target(): print('当前的线程%s
在运行' % threading.current_thread().name) time.sleep(1) print('当前的线程 %s 结束' %
threading.current_thread().name) print('当前的线程 %s 在运行' %
threading.current_thread().name) t = threading.Thread(target=target,args = [])
t.start() #线程启动 print('当前的线程 %s 结束' % threading.current_thread().name)
#####输出:
当前的线程 MainThread 在运行 当前的线程Thread-13 在运行 当前的线程 MainThread 结束 当前的线程 Thread-13 结束
从结果可以看出,主线程结束后,子线程还没有运行结束;这时候为了让子进程先与主进程结束,可以调用join( )函数;
join( )函数:join所完成的工作就是线程同步,即主线程任务结束之前,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止。
join有一个timeout参数:
* 当设置守护线程时【setDaemon(True)】,含义是主线程对于子线程等待timeout的时间将会杀死该子线程,最后退出程序
。所以说,如果有10个子线程,全部的等待时间就是每个timeout的累加和。简单的来说,就是给每个子线程一个timeout的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死。
*
没有设置守护线程时,主线程将会等待timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。
import threading import time def target(): print('当前的线程%s 在运行' %
threading.current_thread().name) time.sleep(1) print('当前的线程 %s 结束' %
threading.current_thread().name) print('当前的线程 %s 在运行' %
threading.current_thread().name) t = threading.Thread(target=target,args = [])
t.start() t.join() #阻塞进程 print('当前的线程 %s 结束' % threading.current_thread().name)
添加join( )阻塞进程后输出:
当前的线程 MainThread 在运行 当前的线程Thread-11 在运行 当前的线程 Thread-11 结束 当前的线程 MainThread 结束
但如果为线程实例添加t.setDaemon(True)守护进程之后,如果不加join语句,那么当主线程结束之后,会杀死子线程。如果加上join,并设置等待时间,就会等待线程一段时间再退出:
首先看一下守护进程机制:
import time def run(): time.sleep(2) print('当前线程的名字是: ',
threading.current_thread().name) time.sleep(2) if __name__ == '__main__':
start_time = time.time() print('这是主线程:', threading.current_thread().name)
thread_list = [] for i in range(5): t = threading.Thread(target=run)
thread_list.append(t) for t in thread_list: t.setDaemon(True) t.start()
print('主线程结束了!' , threading.current_thread().name) print('一共用时:',
time.time()-start_time) ''' 这是主线程: MainThread 主线程结束了! MainThread 一共用时:
0.015624046325683594 当前线程的名字是: 当前线程的名字是: Thread-30 当前线程的名字是: Thread-29
Thread-31 当前线程的名字是: Thread-33 当前线程的名字是: Thread-32 '''
可以看出当设置守护进程t.setDaemon(True)后,主进程结束就结束了整个进程,子进程依旧打印。
然后加上join( ),如果加上join,并设置等待时间,就会等待线程一段时间再退出
import threading import time def target(): print('当前的线程%s 在运行' %
threading.current_thread().name) time.sleep(4) print('当前的线程 %s 结束' %
threading.current_thread().name) print('当前的线程 %s 在运行' %
threading.current_thread().name) t = threading.Thread(target=target,args = [])
t.setDaemon(False) t.start() t.join(5)
#为子线程设定运行的时间,5s后就退出子线程,如果不加等待时间,就会一直等待子线程运行结束后,再运行主线程 print('当前的线程 %s 结束' %
threading.current_thread().name) ''' 当前的线程 MainThread 在运行 当前的线程Thread-35 在运行
当前的线程 Thread-35 结束 当前的线程 MainThread 结束 '''
热门工具 换一换