其实自我感觉Python的多线程很类似于Java的多线程机制,但是比JAVA的多线程更灵活。在早期的Python多线程实现中,采用了thread模块。例如:

  1. from time import ctime,sleep
  2. from thread import start_new_thread
  3. def loop1():
  4. print "enter loop1:",ctime();
  5. sleep(3);
  6. print "leave loop1:",ctime();
  7. def loop2():
  8. print "enter loop2:",ctime();
  9. sleep(5);
  10. print "leave loop2:",ctime();
  11. def main():
  12. print "main begin:",ctime();
  13. start_new_thread(loop1, ());
  14. start_new_thread(loop2,());
  15. sleep(8);
  16. print "main end:",ctime();
  17. if __name__=="__main__":
  18. main();

简单介绍下这个代码块中的函数功能,sleep是线程睡眠时间,几乎等价于JAVA中的Thread.sleep(millionseconds)

start_new_thread是实例化一个线程并运行的方法,方法的第一个参数接受一个线程运行时所执行的函数对象,第二个参数是方法执行时所需要的参数,以一个元组的形式传入。

这大概是最早期的Python多线程实现了,注意代码中的main线程里的sleep(8)。这里的睡眠时间只能比3+5大,而不能小。如果小于这个时间,那么main主线程会提前退出,导致无论其子线程是否是后台线程,都将会中断,从而抛出线程中断异常,类似于Java的ThreadInterruptException。这个致命的影响几乎就是这个模块后期被抛弃的罪魁祸首。

当然在早期的Python多线程中,你可以利用加锁的机制来避免出现这个情况。稍微改动下以上代码:

  1. import thread;
  2. from time import sleep,ctime;
  3. from random import choice
  4. #The first param means the thread number
  5. #The second param means how long it sleep
  6. #The third param means the Lock
  7. def loop(nloop,sec,lock):
  8. print "Thread ",nloop," start and will sleep ",sec;
  9. sleep(sec);
  10. print "Thread ",nloop," end  ",sec;
  11. lock.release();
  12. def main():
  13. seconds=[4,2];
  14. locks=[];
  15. for i in range(len(seconds)) :
  16. lock=thread.allocate_lock();
  17. lock.acquire();
  18. locks.append(lock);
  19. print "main Thread begins:",ctime();
  20. for i,lock in enumerate(locks):
  21. thread.start_new_thread(loop,(i,choice(seconds),lock));
  22. for lock in locks :
  23. while lock.locked() :
  24. pass;
  25. print "main Thread ends:",ctime();
  26. if __name__=="__main__" :
  27. main();

这里对Python线程运行时加入了锁监控机制,介绍下红色字体标志的几个方法(其实红色字体中的lock实质是thread.lockType实例。 ):

从以上介绍可以看出这个Lock类非常类似于JDK5.0中的java.util.concurrent.locks.Lock。不知道Doug Lea有没有参与这个模块的开发,哈哈~~(纯属YY),只是比JAVA中的LOCK类多了一个方法locked,用于检测Lock对象是否还处于加锁的状态。

所以上一个例子的工作原理就是在启动线程的时候,给每个线程都加了一把锁,直到线程运行介绍,再释放这个锁。同时在Python的main线程中用一个while循环来不停的判断每个线程锁已释放。这个方法虽然避免了最开始的例子中人为的时间控制,但是还不方便,高效。

所以在较新的Python版本中,都推荐使用threading模块。

看下threading模块的API,有过JAVA开发经验的会发现它和java.lang.Thread类非常接近。这里需要说的一点就是threading的run方法可以返回函数值,这点在用于跟踪和判断线程运行正常与否非常有作用。

threading模块支持三种方法来创建线程。而前两种方式都与其Thread类有关。看下它的简要说明:

  1. class Thread(_Verbose) :
  2. __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None)

其中target指的是一个具体的函数,或者可调用的类实例(这里指实现了__call__方法的类实例)

第一种方法:指定线程运行的时候调用的函数。举例如下:

  1. from time import ctime,sleep
  2. import threading;
  3. from random import choice
  4. def loop(number,sec):
  5. print "Thread ",number," begins and will sleep ",sec," at ",ctime();
  6. sleep(sec);
  7. print "Thread ",number,"ends at ",ctime();
  8. def main():
  9. seconds=[2,4];
  10. threads=[];
  11. array=range(len(seconds));
  12. for i in array :
  13. t=threading.Thread(target=loop,args=(i,choice(seconds)));
  14. threads.append(t);
  15. print "main Thread begins at ",ctime();
  16. for t in threads :
  17. t.start();
  18. for t in threads :
  19. t.join();
  20. print "main Thread ends at ",ctime();
  21. if __name__=="__main__" :
  22. main();

从图上可以看出,这里target指向了一个具体的函数对象,而args传入了该方法调用时所必须的参数。这里传入了一个随即的睡眠时间。其中thread.join表示要等待该线程终止,和java中的Thread.join(long millionseconds)作用一样,如果不指定具体的时间的话,将会一直等待下去。

第二种方法就是指定一个可调用的类实例,实际上与前面一种非常的接近。如下所示:

  1. from time import ctime,sleep
  2. import threading;
  3. from random import choice
  4. class ThreadFunc(object):
  5. def __init__(self,func,args,name):
  6. self.func=func;
  7. self.args=args;
  8. self.name=name;
  9. def __call__(self):
  10. self.func(*self.args);
  11. def loop(number,sec):
  12. print "Thread ",number," begins and will sleep ",sec," at ",ctime();
  13. sleep(sec);
  14. print "Thread ",number,"ends at ",ctime();
  15. def main():
  16. seconds=[2,4];
  17. threads=[];
  18. array=range(len(seconds));
  19. for i in array :
  20. t=threading.Thread(target=ThreadFunc(loop,(i,choice(seconds)),loop.__name__));
  21. threads.append(t);
  22. print "main Thread begins at ",ctime();
  23. for t in threads :
  24. t.start();
  25. for t in threads :
  26. t.join();
  27. print "main Thread ends at ",ctime();
  28. if __name__=="__main__" :
  29. main();

这里只是将target指向从一个函数对象变成了一个可调用的类实例。

重点推荐下第三种方式,用继承threading.Thread的方式来实现线程,有过Java多线程应用的朋友一定会对下面的例子非常熟悉。

  1. from time import ctime,sleep
  2. import threading;
  3. from random import choice
  4. class MyThread(threading.Thread):
  5. def __init__(self,func,args,name):
  6. super(MyThread,self).__init__();
  7. self.func=func;
  8. self.args=args;
  9. self.name=name;
  10. def run(self):
  11. self.result=self.func(*self.args);
  12. def getResult(self):
  13. return self.result;
  14. def loop(number,sec):
  15. print "Thread ",number," begins and will sleep ",sec," at ",ctime();
  16. sleep(sec);
  17. print "Thread ",number,"ends at ",ctime();
  18. def main():
  19. seconds=[2,4];
  20. threads=[];
  21. array=range(len(seconds));
  22. for i in array :
  23. t=MyThread(loop,(i,choice(seconds)),loop.__name__);
  24. threads.append(t);
  25. print "main Thread begins at ",ctime();
  26. for t in threads :
  27. t.start();
  28. for t in threads :
  29. t.join();
  30. print "main Thread ends at ",ctime();
  31. if __name__=="__main__" :
  32. main();

从上面可以看出MyThread继承了threading.Thread类,并在初始化方法中执行了必要的参数赋值。值得注意的是在Java类的继承中,如果不显示的指定调用父类的构造方法,那么默认将调用父类的无参构造方法。而在Python中,就不会主动去调用。所以这里需要显示的调用父类的初始化方法。

推荐一个网站:程序人生

【跟我一起学Python吧】Python 多线程的更多相关文章

  1. Python爬虫之多线程

    详情点我跳转 关注公众号"轻松学编程"了解更多. 多线程 在介绍Python中的线程之前,先明确一个问题,Python中的多线程是假的多线程! 为什么这么说,我们先明确一个概念,全 ...

  2. python高级之多线程

    python高级之多线程 本节内容 线程与进程定义及区别 python全局解释器锁 线程的定义及使用 互斥锁 线程死锁和递归锁 条件变量同步(Condition) 同步条件(Event) 信号量 队列 ...

  3. python 类变量 在多线程下的共享与释放问题

    最近被多线程给坑了下,没意识到类变量在多线程下是共享的,还有一个就是没意识到 内存释放问题,导致越累越大 1.python 类变量 在多线程情况 下的 是共享的 2.python 类变量 在多线程情况 ...

  4. python中的多线程【转】

    转载自: http://c4fun.cn/blog/2014/05/06/python-threading/ python中关于多线程的操作可以使用thread和threading模块来实现,其中th ...

  5. Python之FTP多线程下载文件之分块多线程文件合并

    Python之FTP多线程下载文件之分块多线程文件合并 欢迎大家阅读Python之FTP多线程下载系列之二:Python之FTP多线程下载文件之分块多线程文件合并,本系列的第一篇:Python之FTP ...

  6. Python之FTP多线程下载文件之多线程分块下载文件

    Python之FTP多线程下载文件之多线程分块下载文件 Python中的ftplib模块用于对FTP的相关操作,常见的如下载,上传等.使用python从FTP下载较大的文件时,往往比较耗时,如何提高从 ...

  7. Python系列之多线程、多进程

    线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程. Python的标准库提供 ...

  8. Python 简单理解多线程

    进程,是一个或多个线程的集合,每个进程在内存中是相对独立的. 线程,是计算机最小的运算单元,每个进程至少要有一个线程,多个线程时,每个线程间之间共享内存. 分别举例常规运行和多线程运行: 0)常规运行 ...

  9. python中的多线程

    一个程序可以理解为一个进程,这个进程有其代号,可以依据这个代号将其杀死. 一个进程肯定有且只有一个主线程,他可以有很多子线程. 运行一个任务如果可以有许多子线程同时去做,当然会提高效率. 但是,在py ...

  10. python单线程,多线程和协程速度对比

    在某些应用场景下,想要提高python的并发能力,可以使用多线程,或者协程.比如网络爬虫,数据库操作等一些IO密集型的操作.下面对比python单线程,多线程和协程在网络爬虫场景下的速度. 一,单线程 ...

随机推荐

  1. http怎样保持有状态?

    HTTP协议的特点 HTTP协议是无状态的协议,发送的请求不记录用户的状态,不记录用户的信息.就相当于它被访问了2次,不知道是哪两人访问的,或者是一个人访问两次. 正是因为HTTP协议的这一特点,用户 ...

  2. TCL语言笔记:TCL中的数组

    一.介绍 Tcl 中的数组和其他高级语言的数组有些不同:Tcl 数组元素的索引,或称键值,可以是任意的字符串,而且其本身没有所谓多维数组的概念.数组的存取速度要比列表有优势,数组在内部使用散列表来存储 ...

  3. C# 常用对象的的修饰符

    class(类) 1.internal 表示类只能在当然程序集中访问,类默认修饰符 2.public 表示所有地方都可以访问,与internal是互斥的 3.abstract 抽象类,不能被实例化,只 ...

  4. Android ListView高度自适应和ScrollView冲突解决

    在ScrollView中嵌套使用ListView,ListView只会显示一行到两行的数据.起初我以为是样式的问题,一直在对XML文件的样式进行尝试性设置,但始终得不到想要的效果.后来在网上查了查,S ...

  5. Android开发之创建桌面快捷方式

    Android创建桌面快捷方式就是在桌面这个应用上创建一个快捷方式,桌面应用:launcher2 通过查看launcher2的清单文件: <!-- Intent received used to ...

  6. Java Swing中Substance常用皮肤

    AutumnSkin; BusinessSkin; BusinessBlackSteelSkin; BusinessBlueSteelSkin; ChallengerDeepSkin; CremeSk ...

  7. 学军NOI训练13 T3 白黑树

    唉,大学军有自己的OJ就是好,无限orz 只有周六的比赛是开放的囧,这场比赛最后因为虚拟机卡住没有及时提交…… 否则就能让大家看到我有多弱了…… 前两题题解写的很详细,可以自己去看,我来随便扯扯T3好 ...

  8. uva12034Race

    递推,组合. 考虑第一名有i个人,则f[n]=sum(C(n,i)*f[n-i]),递推即可.. #include<cstdio> #include<algorithm> #i ...

  9. LA 2797 (平面直线图PLSG) Monster Trap

    题意: 平面上有n条线段,一次给出这n条线段的两个端点的坐标.问怪兽能否从坐标原点逃到无穷远处.(两直线最多有一个交点,且没有三线共交点的情况) 分析: 首先说明一下线段的规范相交:就是交点唯一而且在 ...

  10. UVA 11396 Claw Decomposition(二分图)

    以“爪”形为单元,问所给出的无向图中能否被完全分割成一个个单元. 分析图的性质,由于已知每个点的度是3,所以“爪”之间是相互交错的,即把一个“爪”分为中心点和边缘点,中心点被完全占据,而边缘点被三个“ ...