多线程
科技在发展,时代在进步,我们的CPU也越来越快,CPU抱怨,P大点事儿占了我一定的时间,其实我同时干多个活都没问题的;于是,操作系统就进入了多任务时代。我们听着音乐吃着火锅的不在是梦想。
线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。
线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所
拥有的全部资源。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行
python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点,在threading 得到了弥补,为了不浪费你和时间,所以我们直接学习threading 就可以了。
下面代码实现通过threading来同时播放音乐和视频。
首先,导入threading模块,这是使用多线程的前提。
import threading
播放音乐和视频的函数定义
def music(func):
for i in range(2):
print "I was listening to %s. %s" %(func,ctime())
sleep(1)
def move(func):
for i in range(2):
print "I was at the %s! %s" %(func,ctime())
sleep(5)
创建了threads数组,创建线程t1,使用threading.Thread()方法,在这个方法中调用music方法target=music,args方法对music进行传参。 把创建好的线程t1装到threads数组中。
接着以同样的方式创建线程t2,并把t2也装到threads数组。
threads = []
t1 = threading.Thread(target=music,args=(u'爱情买卖',))
threads.append(t1)
最后再通过for循环遍历数组(数组被装载了t1和t2两个线程)。
for t in threads:
t.setDaemon(True)
t.start()
上面的t.setDaemon(True)将线程声明为守护线程,必须在start() 方法调用之前设置,如果不设置为守护线程程序会被无限挂起。子线程启动后,父线程也继续执行下去,当父线程执行完最后一条语句print “all over %s” %ctime()后,没有等待子线程,直接就退出了,同时子线程也一同结束。
t.start()开始线程活动。
完整代码
#coding=utf-8
import threading
from time import ctime,sleep
def music(func):
for i in range(2):
print "I was listening to %s. %s" %(func,ctime())
sleep(1)
def move(func):
for i in range(2):
print "I was at the %s! %s" %(func,ctime())
sleep(5)
threads = []
t1 = threading.Thread(target=music,args=(u'爱情买卖',))
threads.append(t1)
t2 = threading.Thread(target=move,args=(u'阿凡达',))
threads.append(t2)
if __name__ == '__main__':
for t in threads:
t.setDaemon(True)
t.start()
print "all over %s" %ctime()
音乐播放需要1秒钟,每一场电影需要5秒钟,sleep()来控制播放的时长。
运行结果:
I was listening to 爱情买卖. Thu Apr 17 12:51:45 2014 I was at the 阿凡达! Thu Apr 17 12:51:45 2014 all over Thu Apr 17 12:51:45 2014
从执行结果来看,子线程(muisc 、move )和主线程(print “all over %s” %ctime())都是同一时间启动,但由于主线程执行完结束,所以导致子线程也终止。
代码修改1
针对上述问题,调整程序:
...
if __name__ == '__main__':
for t in threads:
t.setDaemon(True)
t.start()
for t in threads:
t.join()
print "all over %s" %ctime()
在原本的代码中加入join()方法,用于等待线程终止。join()的作用是在子线程完成前,该子线程的父线程将一直被阻塞。
运行结果:
I was listening to 爱情买卖. Thu Apr 17 13:04:11 2014 I was at the 阿凡达! Thu Apr 17 13:04:11 2014
I was listening to 爱情买卖. Thu Apr 17 13:04:12 2014
I was at the 阿凡达! Thu Apr 17 13:04:16 2014
all over Thu Apr 17 13:04:21 2014
开始时间4分11秒,直到调用主进程为4分21秒,总耗时为10秒。
代码修改2
把music的sleep()的时间调整为4秒。
...
def music(func):
for i in range(2):
print "I was listening to %s. %s" %(func,ctime())
sleep(4)
...
运行结果:
I was listening to 爱情买卖. Thu Apr 17 13:11:27 2014I was at the 阿凡达! Thu Apr 17 13:11:27 2014
I was listening to 爱情买卖. Thu Apr 17 13:11:31 2014
I was at the 阿凡达! Thu Apr 17 13:11:32 2014
all over Thu Apr 17 13:11:37 2014
子线程启动11分27秒,主线程运行11分37秒。虽然music每首歌曲从1秒延长到了4 ,但通多程线的方式运行脚本,总的时间没变化。