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

 

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. tcpdump 学习(3):MySQL Query

    在MySQL线上环境我们一般只打开了binary log,slow log,有时我们需要查看general log呢?因为该log记录所有的请求,打开该日志肯定给磁盘造成很大压力,IO能力有所下降,所 ...

  2. 经常用到的Eclipse快捷键(更新中....)

    alt+shift+s:弹出Source选项,用于生成get,set等方法. Ctrl+E:快速显示当前Editer的下拉列表 alt+shift+r:重命名 Ctrl+Shift+→/Ctrl+Sh ...

  3. Interface与abstract类的区别

    含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象.含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必 ...

  4. 华为MateBook笔记本对比微软Surface Pro 4,谁更好?

    继上网本.超极本等概念之后,变形本和二合一设备逐渐升温,今年终于整体爆发,继苹果的iPad Pro.微软的Surface Pro 4之后,华为推出了自己的第一部电脑产品同时也是二合一设备的华为Mate ...

  5. AC日记——由乃与大母神原型和偶像崇拜 洛谷 P3792

    由乃与大母神原型和偶像崇拜 思路: 逆元+线段树维护和+线段树维护平方和+线段树维护最大最小值: 代码: #include <bits/stdc++.h> using namespace ...

  6. HDU 2562 奇偶位互换(字符串,水)

      奇偶位互换 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  7. 使用 Hibernate 完成 HibernateUtils 类 (适用于单独使用Hibernate或Struts+Hibernate)

    package com.istc.Utilities; import org.hibernate.Session; import org.hibernate.SessionFactory; impor ...

  8. Codeforces 785E Anton and Permutation(分块)

    [题目链接] http://codeforces.com/contest/785/problem/E [题目大意] 一个1到n顺序排列的数列,每次选择两个位置的数进行交换,求交换后的数列的逆序对数 [ ...

  9. AOJ 2230 How to Create a Good Game(费用流)

    [题目链接] http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2230 [题目大意] 给出一张图,从1到n的最长路不变的情况下, 还能 ...

  10. c pvr转存pvr.ccz格式 (转 http://www.cnblogs.com/howeho/p/3586379.html)

    pvr.ccz 是把pvr用zlib算法压缩后的图像格式,其优点是可以提升文件读取效率. 大多数情况下我们可以用一些工具来将pvr压缩到pvr.ccz ,下面提供一个c++方法来完成这个过程 int ...