之前讲了多线程的一篇博客,感觉讲的意犹未尽,其实,多线程非常有意思。因为我们在使用电脑的过程中无时无刻都在多进程和多线程。我们可以接着之前的例子继续讲。请先看我的上一篇博客。

通俗易懂的python多线程实例

从上面例子中发现线程的创建是颇为麻烦的,每创建一个线程都需要创建一个tx(t1、t2、...),如果创建的线程多时候这样极其不方便。下面对通过例子进行继续改进:

player.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2016-02-26 15:52:16
# @Author  : Aries (i@iw3c.com)
# @Link    : http://iw3c.com
# @Version : $Id$

import threading
from time import ctime,sleep
def musics(name):
	for i in range(2):
		print "我正在听音乐:%s ,%s" % (name,ctime())
		sleep(2)
def movies(name):
	for i in range(2):
		print "我正在看电影:%s ,%s" %(name,ctime())
		sleep(5)


def player(name):
	r = name.split('.')[1];
	if 'mp3'==r:
		musics(name)
	else :
		if 'mp4'==r:
			movies(name)
		else:
			print "不好意思,这种格式我不认识"

lists=['似是故人来.mp3','突袭2.mp4']
threads = []
lens = len(lists)
#创建线程
for f in range(lens):
	t = threading.Thread(target=player,args=(lists[f],))
	threads.append(t)

if __name__ == '__main__':
	for t in threads:
		t.start()

	for t in threads:
		t.join()

	print "完事儿了:%s" % ctime()

有趣的是我们又创建了一个player()函数,这个函数用于判断播放文件的类型。如果是mp3格式的,我们将调用music()函数,如果是mp4格式的我们调用move()函数。哪果两种格式都不是那么只能告诉用户你所提供有文件我播放不了。

然后,我们创建了一个list的文件列表,注意为文件加上后缀名。然后我们用len(list) 来计算list列表有多少个文件,这是为了帮助我们确定循环次数。

接着我们通过一个for循环,把list中的文件添加到线程中数组threads[]中。接着启动threads[]线程组,最后打印结束时间。

运行结果:

我正在听音乐似是故人来.mp3 ,Fri Feb 26 16:08:04 2016
我正在看电影突袭2.mp4 ,Fri Feb 26 16:08:04 2016
我正在听音乐似是故人来.mp3 ,Fri Feb 26 16:08:06 2016
我正在看电影突袭2.mp4 ,Fri Feb 26 16:08:09 2016
完事儿了Fri Feb 26 16:08:14 2016
[Finished in 10.1s]

只要我们向lists中添加一个项,就会多创建一个线程。

好,下面我们来优化一下我们的代码。

new_player.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2016-02-26 16:15:31
# @Author  : Aries (i@iw3c.com)
# @Link    : http://iw3c.com
# @Version : $Id$

import threading
from time import ctime,sleep
def player(name,sleepTime):
	for i in range(2):
		print "正在播放:%s ,%s" % (name,ctime())
		sleep(sleepTime)


#字典:播放的文件与播放时长
lists = {'突袭2.mp4':5,'似是故人来.mp3':2,'天涯.mp3':3}
threads = []
lens = len(lists)

#n = name ,t = time
for n,t in lists.items():
	t = threading.Thread(target=player,args=(n,t))
	threads.append(t)

if __name__ == '__main__':
	for t in threads:
		t.start()

	for t in threads:
		t.join()

	print "完事儿了:%s" % ctime()

首先创建字典lists ,用于定义要播放的文件及时长(秒),通过字典的items()方法来循环的取name和time,取到的这两个值用于创建线程。

接着创建player()函数,用于接收name和time,用于确定要播放的文件及时长。

最后是线程启动运行。运行结果:

正在播放似是故人来.mp3 ,Fri Feb 26 16:22:15 2016
正在播放天涯.mp3 ,Fri Feb 26 16:22:15 2016
正在播放突袭2.mp4 ,Fri Feb 26 16:22:15 2016
正在播放似是故人来.mp3 ,Fri Feb 26 16:22:17 2016
正在播放天涯.mp3 ,Fri Feb 26 16:22:18 2016
正在播放突袭2.mp4 ,Fri Feb 26 16:22:20 2016
完事儿了Fri Feb 26 16:22:25 2016
[Finished in 10.1s]

再优化,我们要用自己的多线程类。

class.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2016-02-26 16:24:26
# @Author  : Aries (i@iw3c.com)
# @Link    : http://iw3c.com
# @Version : $Id$

import threading
from time import ctime,sleep
class MyThread(threading.Thread):
	def __init__(self,func,args,name=''):
		threading.Thread.__init__(self)
		self.name = name
		self.func = func
		self.args = args
	def run(self):
		apply(self.func,self.args)

def player(name,sleepTime):
	for i in range(2):
		print "正在播放:%s ,%s" % (name,ctime())
		sleep(sleepTime)

#字典:播放的文件与播放时长
lists = {'突袭2.mp4':5,'似是故人来.mp3':2,'天涯.mp3':3}
threads = []
lens = len(lists)

for n,t in lists.items():
	t = MyThread(player,(n,t),player.__name__)
	threads.append(t)


if __name__ == '__main__':
	for t in threads:
		t.start()

	for t in threads:
		t.join()

	print "完事儿了:%s" % ctime()
MyThread(threading.Thread)

创建MyThread类,用于继承threading.Thread类。

__init__()

使用类的初始化方法对func、args、name等参数进行初始化。

apply()

apply(func [, args [, kwargs ]]) 函数用于当函数参数已经存在于一个元组或字典中时,间接地调用函数。args是一个包含将要提供给函数的按位置传递的参数的元组。如果省略了args,任何参数都不会被传递,kwargs是一个包含关键字参数的字典。

apply() 用法:

#不带参数的方法
>>> def say():
    print 'say in'

>>> apply(say)
say in

#函数只带元组的参数
>>> def say(a,b):
    print a,b

>>> apply(say,('hello','虫师'))
hello 虫师

#函数带关键字参数
>>> def say(a=1,b=2):
    print a,b

    
>>> def haha(**kw):
    apply(say,(),kw)

    
>>> haha(a='a',b='b')
a b

MyThread(play,(k,v),play.name)

由于MyThread类继承threading.Thread类,所以,我们可以使用MyThread类来创建线程。

运行结果:

正在播放似是故人来.mp3 ,Fri Feb 26 16:29:41 2016
正在播放天涯.mp3 ,Fri Feb 26 16:29:41 2016
正在播放突袭2.mp4 ,Fri Feb 26 16:29:41 2016
正在播放似是故人来.mp3 ,Fri Feb 26 16:29:43 2016
正在播放天涯.mp3 ,Fri Feb 26 16:29:44 2016
正在播放突袭2.mp4 ,Fri Feb 26 16:29:46 2016
完事儿了Fri Feb 26 16:29:51 2016
[Finished in 10.1s]

所有的源码下载:http://pan.baidu.com/s/1pK5ziqR 密码: dce6