对于Python中的多线程,理解起来没有基础还是比较困难的,首先需要了解线程与进程的关系:http://blog.csdn.net/misayaaaaa/article/details/53199608 这里推荐我的另一片文章,希望可以帮助大家理解。
做一个比喻吧,我现在像做两件事,听歌和看电影,单线程的话就需要将两件事进行排序,按次序分时进行。而多线程允许我们同时进行多项任务(谁叫我们是小天才呢~),可以同时听歌和看电影。
先上代码理解下单线程吧
from time import ctime,sleep
def music():
for i in range(2):
print "I was listening to music. %s" %ctime()
sleep(1)
def move():
for i in range(2):
print "I was watching the movies! %s" %ctime()
sleep(5)
if __name__ == '__main__':
music()
move()
print "The end time is %s" %ctime()
首先time模块的sleep()函数表示的是推迟进程的运行,表示该进程挂起的时间。ctime()表示的是调用当前时间,返回字符串,对应%s。
结果:
各个线程分步进行。
现在我们想要同时听歌和看电影怎么办呢?这就要用到Python中的threading模块了,thread模块也可,但是相较于threading,thread有一些缺点。我们只要用threading就好了。
#coding=utf-8
from time import ctime, sleep
import threading #导入必要模块
def music():#分别定义两个线程
for i in range(2):
print "I am listening to music %s" %ctime()
sleep(1)
def movie():
for i in range(2):
print "I am watching the movie %s" %ctime()
sleep(5)
threads = [] #定义threads数组
t1 = threading.Thread(target=music) #创建线程t1
threads.append(t1) #存入线程t1
t2 = threading.Thread(target=movie)
threads.append(t2)
if __name__ == '__main__':
for t in threads: #遍历数字中存放的两个线程
t.setDaemon(True) #线程声明为守护线程
t.start()
print "The end time is %s"%ctime
结果为:
可以看出线程的运行时间是相同的,但是为什么只有一句呢?,那是因为线程又分子线程和父线程,父线程终止之后,子线程也会终止。
我们在修改一下程序;
#coding=utf-8
from time import ctime, sleep
import threading #导入必要模块
def music():#分别定义两个线程
for i in range(2):
print "I am listening to music %s" %ctime()
sleep(1)
def movie():
for i in range(2):
print "I am watching the movie %s" %ctime()
sleep(5)
threads = [] #定义threads数组
t1 = threading.Thread(target=music) #创建线程t1
threads.append(t1) #存入线程t1
t2 = threading.Thread(target=movie)
threads.append(t2)
if __name__ == '__main__':
for t in threads: #遍历数字中存放的两个线程
t.setDaemon(True) #线程声明为守护线程
t.start()
t.join() #用于等待所有线程终止。join()的作用是,在子线程完成运行之前,这个子线程的父线程将一直被阻塞。
# 注意: join()方法的位置是在for循环外的,也就是说必须等待for循环里的两个进程都结束后,才去执行主进程。
#注意这里的 t 即使在for循环之外也是可以被识别的,在Python中是比较特别的地方!就是最后的线程!!!
print "The end time is %s"%ctime
结果:
线程同时开始,但结束的时间不一样~~哈哈哈~~
这样的话多线程的简单理解是不是就通俗多了~~
这里贴上threading 的Thread说明
class threading.Thread():
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
This constructor should always be called with keyword arguments. Arguments are:
group should be None; reserved for future extension when a ThreadGroup class is implemented.
target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.
name is the thread name. By default, a unique name is constructed of the form “Thread-N” where N is a small decimal number.
args is the argument tuple for the target invocation. Defaults to ().
kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}.
If the subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing
anything else to the thread.