【跟我一起学Python吧】Python 多线程

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

Python代码  

  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多线程中,你可以利用加锁的机制来避免出现这个情况。稍微改动下以上代码:

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类有关。看下它的简要说明:

Python代码  

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

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

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

Python代码  

  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)作用一样,如果不指定具体的时间的话,将会一直等待下去。

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

Python代码  

  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多线程应用的朋友一定会对下面的例子非常熟悉。

Python代码  

  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中,就不会主动去调用。所以这里需要显示的调用父类的初始化方法。

推荐一个网站:程序人生

时间: 2024-08-06 01:20:46

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

[零基础学pythyon]安装python编程环境

任何高级语言都是需要一个自己的编程环境的,这就好比写字一样,需要有纸和笔,在计算机上写东西,也需要有文字处理软件,比如各种名称的OFFICE.笔和纸以及office软件,就是写东西的硬件或软件,总之,那些文字只能写在那个上边,才能最后成为一篇文章.那么编程也是,要有个什么程序之类的东西,要把程序写到那个上面,才能形成最后类似文章那样的东西. 刚才又有了一个术语--"程序",什么是程序?本文就不讲了.如果列为观众不是很理解这个词语,请上网google一下. 注:推荐一种非常重要的学习方法

python中的多线程

一个程序可以理解为一个进程,这个进程有其代号,可以依据这个代号将其杀死. 一个进程肯定有且只有一个主线程,他可以有很多子线程. 运行一个任务如果可以有许多子线程同时去做,当然会提高效率. 但是,在python中,多线程其实不是严格意义上的多线程. 因为,python有一个全局锁的概念,它保证在某一个时间节点上,只能存在一个线程在运行,只是这个时间节点非常短,人类意识不到. 所以说,Python的多线程其实就是不断地切换进程,而没有把所有的进程在同一时间同时运行. 注意,切换进程并不是依据什么顺序

(转)python多进程、多线程编程

1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务.一个线程是一个execution context(执行上下文),即一个cpu执行时所需要的一串指令. 1.1.2 线程的工作方式 假设你正在读一本书,没有读完,你想休息一下,但是你想在回来时恢复到当时读的具体进度.有一个方法就是记下页数.行数与字数这三个数值,这

python高级之多线程

python高级之多线程 本节内容 线程与进程定义及区别 python全局解释器锁 线程的定义及使用 互斥锁 线程死锁和递归锁 条件变量同步(Condition) 同步条件(Event) 信号量 队列Queue Python中的上下文管理器(contextlib模块) 自定义线程池 1.线程与进程定义及区别 线程的定义: 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同

python中的多线程【转】

转载自: http://c4fun.cn/blog/2014/05/06/python-threading/ python中关于多线程的操作可以使用thread和threading模块来实现,其中thread模块在Py3中已经改名为_thread,不再推荐使用.而threading模块是在thread之上进行了封装,也是推荐使用的多线程模块,本文主要基于threading模块进行介绍.在某些版本中thread模块可能不存在,要使用dump_threading来代替threading模块. 线程创

python之路-----多线程与多进度

一.进程和线程的概念 1.进程(最小的资源单位): 进程:就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成. 程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成: 数据集;则是程序在执行过程中所需要使用的资源: 进程控制块:用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志. 进程比线程更早出现,计算机早期处理代码时,使用的是串行的方法,假设计算机在运行A,B,C三个软件,需要A运行完了

Python系列之多线程、多进程

一.python多线程 线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程. Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,threading是高级模块,对_thread进行了封装.绝大多数情况下,我们只需要使用threading这个高级模块. import threading import time def f1(num)

14-08-07 关于程序、进程、线程,以及python中实现多线程的办法

考核题目中涉及到多线程编程,于是复习了一下系统编程里面的各种概念. 首先,程序是代码,没有活动.通过编译连接之后被加载到内存里运行时,内存活动的就是进程,这里的进程不仅仅是代码段,还包括涉及的数据等.而线程是在同一个进程下的小程序,它们可以"同时"地运行,其中会有一个主线程来控制. 接下来是多线程或着多进程的实现,两者原理基本一样,都是把CPU的时间分片然后进行分配给某个进程或者线程,也就是说在同一个时间只会有一个线程在使用CPU,但是CPU切换线程的频率非常快使得它们看上去是在同一个

重学Python - Day 01 - python基础 -> python版本选择+第一个小程序

题外话: Python版本:最新的3.6 安装注意点:勾选添加路径后自定义安装到硬盘的一级目录,例如本人的安装路径: F:\Python 原因:可以自动添加python环境变量,自动关联.py文件,其余的优点很多,例如学习selenium的,使用pip install selenium命令就可以安装selenium 3了,虽然python webdriver的自动化还是2.7居多,但是3.0会是未来 闲言碎语以后再说,现在正式开始学习Python,没办法,不会编程的测试在工作中好吃力,学不会py

python并发编程&多线程(一)

本篇理论居多,实际操作见:  python并发编程&多线程(二) 一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线 流水线的工作需要电源,电源就相当于cpu 所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位. 多线程(即多个控制线程)的概念