这节记录学习多线程的心得。

 

Python提供了thread模块,不过该模块的缺点很多,例如无法方便的等待线程结束,所以我们使用更加高级的threading模块。

 

threading模块的使用一共三种模式:

1.利用函数生成一个Thread实例

2.利用函数生成一个可以调用的类对象,生成一个Thread实例

3.从Thread派生一个子类,创建这个子类的实例

 

利用函数生成Thread实例

 

第一种使用方式最为简单,代码如下:

import threading
from time import sleep def threadFunc():
i = 10;
while i > 0:
print 'i = %d' % i
i -= 1 if __name__ == '__main__':
t = threading.Thread(target = threadFunc)
t.start()
t.join()

这段代码的逻辑很简单,就是在线程中执行threadFunc这个函数。

如果该函数需要参数的话,在

t = threading.Thread(target = threadFunc)

这一行添加一个参数即可,如下:

import threading
from time import sleep def threadFunc(i):
while i > 0:
print 'i = %d' % i
i -= 1 if __name__ == '__main__':
t = threading.Thread(target = threadFunc, args = [10])
t.start()
t.join()

注意args参数必须使用元组或者列表。

 

利用函数生成一个可以调用的类对象,生成一个Thread实例

 

我们先补充一些知识,C++中有函数对象,就是对某一个类重载函数调用操作符,那么该类的对象就可以当做函数来使用,python中也有同样的机制:

class Foo():
def __call__(self):
print 'foobar' if __name__ == '__main__':
f = Foo()
f()

此例中f是一个对象,但可以当做函数使用。当调用f()时,解释器调用了Foo中的__call__方法,相当于C++中的operator()操作符被重载。

 

还有一个关于apply的知识点:

def test(i):
print 'i = %d' % i if __name__ == '__main__':
apply(test, [1])

apply可以这样调用函数。通过这种机制,我们可以将函数存储起来,选择合适的时机注意调用。

from random import randint

def foo(i):
print 'i = %d' % i
def bar(i):
print 'i*i = %d' % (i*i) class Foo():
def __call__(self, i):
print 'foobar: %d' % i if __name__ == '__main__':
funcs = [foo, bar, Foo()]
for func in funcs:
i = randint(1, 4)
apply(func, [i])

 

于是我们可以将函数存储在类中,为该类提供__call__函数,此时这个类的对象也是可以执行的,所以我们利用这个对象去生成Thread。

#coding: utf-8
import threading
from time import sleep class ThreadFunc(object):
def __init__(self, func, args):
self.func = func
self.args = args def __call__(self):
apply(self.func, self.args) def loop(i):
while i > 0:
print 'i = %d' % i
sleep(0.5)
i -= 1 if __name__ == '__main__':
print '在主线程内执行这个函数'
t1 = ThreadFunc(loop, [5])
t1() print '开始执行一个新的线程'
t2 = threading.Thread(target = t1)
t2.start()
t2.join()
print '线程执行完毕' print '开始执行一个新的线程'
t3 = threading.Thread(target = ThreadFunc(loop, [3]))
t3.start()
t3.join()
print '线程执行完毕'

t1是个ThreadFunc的实例,既可以直接执行,又可以使用它去生成Thread实例。

 

从Thread派生一个子类,创建这个子类的实例

 

最简单的使用方式如下:

import threading
from time import sleep class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.count = 10 def run(self):
while self.count > 0:
print 'i = %d' % self.count
sleep(1)
self.count -= 1 if __name__ == '__main__':
t = MyThread();
t.start()
t.join()

我们去继承Thread类,然后覆盖其中的run方法,这与Java的Thread使用相一致。

创建多个线程可以这样:

import threading
from time import sleep class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self) def run(self):
print 'begin .....'
sleep(5)
print 'end.....' if __name__ == '__main__':
threads = []
for i in range(10):
t = MyThread()
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()

 

不过,目前我们的线程逻辑是固定的,可以借鉴第二种方式,从外部传入逻辑,存储起来。

#coding: utf-8
import threading
from time import sleep class CustomThread(threading.Thread):
def __init__(self, func, args):
threading.Thread.__init__(self)
self.func = func
self.args = args def run(self):
apply(self.func, self.args) def loop(i):
while i > 0:
print 'i = %d' % i
sleep(0.5)
i -= 1 if __name__ == '__main__':
t = CustomThread(loop, [10])
t.start()
t.join()

这里跟第二种不同的是:

1.采用了继承,基类是Thread

2.覆盖run方法,而不是提供__call__方法

3.使用时直接创建该类的实例

以上三种,我个人感觉第三种最方便,在大一些程序中,可以将该Thread单独做成一个模块。

另外,前两种的本质是一样的,都是向Thread传入一个可以执行的对象(python中函数也是对象)。

 

完。

Python学习笔记(三)多线程的使用的更多相关文章

  1. Python 学习笔记三

    笔记三:函数 笔记二已取消置顶链接地址:http://www.cnblogs.com/dzzy/p/5289186.html 函数的作用: 給代码段命名,就像变量給数字命名一样 可以接收参数,像arg ...

  2. webdriver(python) 学习笔记三

    知识点:简单的对象定位 对象的定位应该是自动化测试的核心,要想操作一个对象,首先应该识别这个对象.一个对象就是一个人一样,他会有各种的特征(属性),如比我们可以通过一个人的身份证号,姓名,或者他住在哪 ...

  3. python学习笔记(十三): 多线程多进程

    一.线程&进程 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程, ...

  4. python学习笔记三--字典

    一.字典: 1. 不是序列,是一种映射, 键 :值的映射关系. 2. 没有顺序和位置的概念,只是把值存到对应的键里面. 3. 通过健而不是通过偏移量来读取 4. 任意对象的无序集合 5. 可变长,异构 ...

  5. Python学习笔记三

    一. 为什么要使用函数? 函数可以方便阅读代码. 函数可以减少重复代码. 函数可以减少管理操作,减少修改操作. 二. 函数分类: 内置函数:len()   sum()   max()   min() ...

  6. python学习笔记(三)、字典

    字典是一种映射类型的数据类型.辣么什么是映射呢?如果看过<数据结构与算法>这一本书的小伙伴应该有印象(我也只是大学学习过,嘻嘻). 映射:就是将两个集合一 一对应起来,通过集合a的值,集合 ...

  7. Python学习笔记三:模块

    一:模块 一个模块就是一个py文件,里面定义了一些业务函数.引用模块,可以用import语句导入.导入模块后,通过 模块.函数名(参数)  来使用模块中的函数.如果存在多个同名模块,则前面模块名需要加 ...

  8. python学习笔记(三)高级特性

    一.切片 list.tuple常常截取某一段元素,截取某一段元素的操作很常用 ,所以python提供了切片功能. L=['a','b','c','d','e','f'] #取索引0,到索引3的元素,不 ...

  9. python学习笔记(三):文件操作和集合

    对文件的操作分三步: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句柄操作文件 3.关闭文件. 文件基本操作: f = open('file.txt','r') #以只读方式打开一个 ...

  10. python学习笔记三:函数及变量作用域

    一.定义 def functionName([arg1,arg2,...]): code 二.示例 #!/usr/bin/python #coding:utf8 #coding=utf8 #encod ...

随机推荐

  1. php多台服务器实现session共享

    使用Redis存储Session(前提是服务期间已实现redis共享,可参照:laravel项目使用twemproxy部署redis集群) 修改php.ini: session.save_handle ...

  2. [loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流

    #6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 ...

  3. scrapy模拟请求头

    import random USER_AGENT_LIST=[ 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, lik ...

  4. codeforces Round #440 C Maximum splitting【数学/素数与合数/思维/贪心】

    C. Maximum splitting time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  5. Jekins持续集成,gitlab代码仓库

    http://blog.csdn.net/john_cdy/article/details/7738393

  6. LCA+差分【CF191C】Fools and Roads

    Description 有一颗 \(n\) 个节点的树,\(k\) 次旅行,问每一条边被走过的次数. Input 第一行一个整数 \(n\) (\(2\leq n\leq 10^5\)). 接下来 \ ...

  7. 主键(PrimaryKey)

    员工表中的每一行记录代表了一个员工,一般员工的名字就能唯一标识这一个员工,但 是名字也是有可能重复的,这时我们就要为每一名员工分配一个唯一的工号: 这样就可以通过这个工号来唯一标识一名员工了.当老板下 ...

  8. Oracle 后台进程

    一.基本后台进程       1.数据库写入进程(DBWn):       数据库写入程序讲数据库告诉缓存区中的修改块写入数据文件.对于多数系统来说,一个数据库写入程序(DBW0)就已经足够,但是对于 ...

  9. JVM加载Class文件的机制

    1.Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的, 类装载器所做的工作实质是把类文件从硬盘读取到内存中 2.java中的类大致分为三种:     1.系统 ...

  10. 【计算几何】【辛普森积分法】UVALive - 7076 - Highway

    春节前后想了好久才在队友的讲解下想明白…… 太难讲了,我就不讲了,大概就是考虑直着走到高速上还是斜着走到高速上,然后平移直线和大圆相切,把生成的最大的“桥”和大圆并一下就行了. #include< ...