0
点赞
收藏
分享

微信扫一扫

创建线程类

除了使用 Python 所提供的线程类外,我们也可以根据需求来创建自己的线程类。

mythread.py

#coding=utf-8

import threading

from time import sleep, ctime

#创建线程类

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 super_play(file,time):

for i in range(2):

print 'Start playing: %s! %s' %(file,ctime())

sleep(time)

list = {'爱情买卖.mp3':3,'阿凡达.mp4':5}

#创建线程

threads = []

files = range(len(list))

for file,time in list.items():

t = MyThread(super_play,(file,time),super_play.__name__)

threads.append(t)

if __name__ == '__main__':

#启动线程

for i in files:

threads[i].start()

for i in files:

threads[i].join()

#主线程

print 'end:%s' %ctime()

MyThread(threading.Thread)

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

__init__() 类的初始化方法对 func、args、name 等参数进行初始化。

apply() 当函数参数已经存在于一个元组或字典中时,间接地调用函数。args 是一个包含将要提供给

函数的按位置传递的参数的元组。如果省略了 args,任何参数都不会被传递,kwargs 是一个包含关键字

参数的字典。

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

多进程技术

multiprocessing 模块

多进程 multiprocessing 模块的使用与多线程 threading 模块类似,multiprocessing 提供了本地和

远程的并发性,有效的通过全局解释锁(Global Interceptor Lock, GIL)来使用进程(而不是线程)。由于

GIL 的存在,在 CPU 密集型的程序当中,使用多线程并不能有效地利用多核 CPU 的优势,因为一个解释器

在同一时刻只会有一个线程在执行。所以,multiprocessing 模块可以充分的利用硬件的多处理器来进行

工作。它支持 Unix 和 Windows 系统上的运行。

修改多线程的例子,将 threading 模块中的 Thread 方法替换为 multiprocessing 模块的 Process 就实现了多进程。

process.py

#coding=utf-8

from time import sleep, ctime

import multiprocessing

def super_player(file,time):

for i in range(2):

print 'Start playing: %s! %s' %(file,ctime())

sleep(time)

#播放的文件与播放时长

list = {'爱情买卖.mp3':3,'阿凡达.mp4':5,'我和你.mp3':4}

threads = []

files = range(len(list))

#创建线程

for file,time in list.items():

t = multiprocessing.Process(target=super_player,args=(file,time))

threads.append(t)

if __name__ == '__main__':

#启动线程

for i in files:

threads[i].start()

for i in files:

threads[i].join()

#主线程

print 'end:%s' %ctime()

从上面的实例中可以看到,多进程的使用,几乎与多线程一样。

我们利用 multiprocessing.Process 对象来创建一个进程。Process 对象与 Thread 对象的用法相同,

也有 start(), run(), join()的方法。

multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={})

target 表示调用对象,args 表示调用对象的位置参数元组。kwargs 表示调用对象的字典。Name 为别

名。Group 实质上不使用。

运行结果:

Python Shell

>>> ================================ RESTART ================================

>>>

Start playing: 爱情买卖.mp3! Sun Feb 15 11:35:46 2015

Start playing: 爱情买卖.mp3! Sun Feb 15 11:35:49 2015

Start playing: 我和你.mp3! Sun Feb 15 11:35:46 2015

Start playing: 我和你.mp3! Sun Feb 15 11:35:50 2015

Start playing: 阿凡达.mp4! Sun Feb 15 11:35:46 2015

Start playing: 阿凡达.mp4! Sun Feb 15 11:35:51 2015

end:Sun Feb 15 11:35:56 2015

从运行结果中还是看出细微的差别,虽然利用多进程任务时间没有变化,但多程的结果显示是以进程

组为顺序进行显示的。

扩展阅读:

在*nix 上面创建的新的进程使用的是 fork:

一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几

乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个

进程也可以做不同的事。

这意味着子进程开始执行的时候具有与父进程相同的全部内容。请记住这点,这个将是下面我们讨

论基于继承的对象共享的基础。所谓基于继承的对象共享,是说在创建子进程之前由父进程初始化的某

些对象可以在子进程当中直接访问到。在 Windows 平台上,因为没有 fork 语义的系统调用,基于继承

的共享对象比*nix 有更多的限制,最主要就是体现在要求 Process 的__init__当中的参数必须可以 Pickle。

但是,并不是所有的对象都是可以通过继承来共享,只有 multiprocessing 库当中的某些对象才可以。

例如 Queue,同步对象,共享变量,Manager 等等。

在一个 multiprocessing 库的典型使用场景下,所有的子进程都是由一个父进程启动起来的,这个父

进程称为 master 进程。这个父进程非常重要,它会管理一系列的对象状态,一旦这个进程退出,子进程

很可能会处于一个很不稳定的状态,因为它们共享的状态也许已经被损坏掉了。因此,这个进程最好尽

可能做最少的事情,以便保持其稳定性。

举报

相关推荐

0 条评论