使用python的threading中的Thread

下面是两种基本的实现线程的方式:

第一种方式————

#coding=utf-8

"""
thread的第一种声明及调用方式
""" from threading import Thread
import time def func():
while True:
print time.ctime()
time.sleep(1) def func1():
while True:
print "func1", time.ctime()
time.sleep(2) #将要执行的方法作为参数传给Thread的构造方法 t = Thread(target=func)
t.start() t1 = Thread(target=func1)
t1.start()

第二种方式————

#coding=utf-8

"""
thread的第二种声明及调用方法
""" import time
from threading import Thread
from time import sleep #从Thread继承,并重写run()
class myThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname) def run(self):
while True:
print self.getName() + " " + time.ctime()
time.sleep(1) t = myThread("thread_1")
t.start() t1 = myThread("thread_2")
t1.start()

接下来是:join和setDaemon的方法调用及具体区别:

join的方法调用:

#coding=utf-8

"""
join方法的含义是:存在A主线程,B子线程,在A主线程中生成了一个子线程B,
如果子线程B调用了join方法,则主线程需要等待子线程操作结束,才能够继续往下执行,主线程会被阻塞
"""
import time
from threading import Thread class myThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name = threadname) def run(self):
time.sleep(10)
print self.getName() + " " + time.ctime() def mainfunc():
for i in range(5):
print i if __name__ == "__main__":
t = myThread("childthread")
t.start()
#增加join方法的调用,则程序运行时的表现是:先子线程(会先sleep 10s,之后打印子线程的内容),再运行主线程中的打印从0到4的逻辑
#不增加join方法的调用,则程序运行时的表现是:会先走主线程的打印从0到4的逻辑,之后子线程(sleep 10s,再打印子线程中的内容),但其实这里就是没有等待子线程
# t.join()
mainfunc()

setDaemon方法的调用:

#coding=utf-8

"""
daemon方法的含义是:存在主线程A,和子线程B,子线程B是从主线程A中生成的
如果设置子线程B为daemon即守护进程,则主线程A不存在的话,子线程B就退出
如果没有设置子线程B为daemon,则主线程A结束运行退出之后,子线程B也不退出
""" import time
from threading import Thread class myThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname) def run(self):
time.sleep(10)
print self.getName() + " " + time.ctime() def mainfunc():
for i in range(5):
print i if __name__ == "__main__":
t = myThread("zixiancheng")
#不设置子线程为守护进程,则主线程退出,子线程继续运行
#设置子线程为守护进程,则主线程退出,子线程直接退出
#并且,需要在start之前调用setDaemon
# t.setDaemon(True)
t.start()
mainfunc()

接下来是线程同步相关的内容:

首先是没有线程同步机制的情况下,多个线程同时操作一个公共数据:

代码如下:

#coding=utf-8

"""
@function: test Thread的Lock
@author: LiXia
@date: 2017-0303
""" """
所有的锁都是为了在线程之间进行通信
例如对一个公共变量进行操作,此例子为没有使用线程同步机制对公共变量进行操作
""" from threading import Thread
import time data = 0 class myThread(Thread):
def __init__(self):
Thread.__init__(self) def run(self):
global data
time.sleep(1)
data += 1
print self.getName() + " data: " + str(data) if __name__ == "__main__":
for i in range(5):
t = myThread()
t.start()

运行结果见下方:

为了能够对公共操作的数据,在特定逻辑内保持一致,需要保证在该逻辑内,只有单个线程可以操作,其他线程需要等待该线程处理结束才可以。

所以下面是关于python线程同步机制提供的指令:

1、Lock:

但是将以上代码中增加上lock处理,注意一定要增加在对公共数据的逻辑判断和处理的前面和后面,所以这里必须添加到while判断之前,释放锁需要在输出操作结束之后添加

即:

#coding=utf-8

"""
所有的锁都是为了在线程之间进行通信
例如对一个公共变量进行操作
""" from threading import Thread
import threading
import time data = 0
lock = threading.Lock() class myThread(Thread):
def __init__(self):
Thread.__init__(self) def run(self):
global data
if lock.acquire():
time.sleep(1)
data += 1
print self.getName() + " data: " + str(data)
lock.release() if __name__ == "__main__":
for i in range(5):
t = myThread()
t.start()

运行结果见下方:

2、RLock

代码如下:

#coding=utf-8

"""
通过RLock(可重入锁)进行线程间的安全通信,RLock为可重入锁,即线程在拥有RLock之后可以继续acquire(),只要保证acquire()次数与
release()次数一致即可;
继续对公共变量进行操作
""" from threading import Thread
import threading
import time rlock = threading.RLock()
data = 0 class myThread(Thread):
def __init__(self):
Thread.__init__(self) def run(self):
global data
if rlock.acquire():
time.sleep(1)
data += 1
print self.getName() + " data:" + str(data) if rlock.acquire():
time.sleep(1)
data -= 1
print self.getName() + " data:" + str(data)
rlock.release()
rlock.release() if __name__ == "__main__":
for i in range(5):
t = myThread()
t.start()

运行结果:

3、Condition

Condition就是条件变量,condition通常与一个锁关联。

acquire([timeout])/release(): 调用关联的锁的相应方法。 
wait([timeout]): 调用这个方法将使线程进入Condition的等待池等待通知,并释放锁。使用前线程必须已获得锁定,否则将抛出异常。 
notify(): 调用这个方法将从等待池挑选一个线程并通知,收到通知的线程将自动调用acquire()尝试获得锁定(进入锁定池);其他线程仍然在等待池中。调用这个方法不会释放锁定。使用前线程必须已获得锁定,否则将抛出异常。 
notifyAll(): 调用这个方法将通知等待池中所有的线程,这些线程都将进入锁定池尝试获得锁定。调用这个方法不会释放锁定。使用前线程必须已获得锁定,否则将抛出异常。

#coding=utf-8

"""
以最经典的生产者和消费者的问题为例,两者需要针对一个公共的数据区域做操作,并且两端需要进行通信
生产者在生产之前,需要先占领地盘,然后开始生产,生产结束通知消费者来取;
消费者在消费的时候,也需要先占领地盘,然后开始消费,消费结束通知生产者继续生产;
当然还有多个生产者和消费者的情况,会更加复杂,可以用python的Queue来实现
""" from threading import Thread
import threading
import time
import random product = []
con = threading.Condition() #得到一个Condition的对象 #生产者线程
class producerThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname) def run(self):
global product
if con.acquire():
while True:
r = random.randint(0, 20)
product.append(r)
print "product len and product: ", self.getName(), product
con.notify()
con.wait()
# time.sleep(2) #消费者线程
class consumerThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname) def run(self):
global product
if con.acquire():
while True:
if product != []:
product.pop()
print "consumer len and product: ", self.getName(), product
con.notify()
con.wait()
time.sleep(2) if __name__ == "__main__":
t1 = producerThread("producer")
t2 = consumerThread("consumer") t1.start()
t2.start()

运行结果如下:

4、对多个生产者消费者支持的很好的Queue

Queue是什么?Queue实现了多生产者-多消费者的队列形式,分别包含先入先出(默认)FIFO、后进先出LIFO、以及优先级队列PriorityQueue(优先级低的先出)

Queue模块的class及exception:

#coding=utf-8

"""
Queue的类和异常
""" import Queue q = Queue.Queue(maxsize = 0) #FIFO的Queue,maxsize即Queue的size值,maxsize≤0表示无size限制 lq = Queue.LifoQueue(maxsize = 0) #LIFO的Queue,先进后出,maxsiz的含义同上 pq = Queue.PriorityQueue(maxsize = 0) #优先级Queue,优先级低的先出,maxsize的含义同上 Queue.Empty() #当Queue的对象为空时,使用非阻塞get时会抛出异常 Queue.Full() #当Queue的对象已满时,使用非阻塞put时会抛出异常

Queue的对象:

Queue(Queue、LifoQueue、PriorityQueue)的对象提供的公共方法如下:

#coding=utf-8

"""
Queue(Queue、LifoQueue、PriorityQueue)的对象的公共方法
""" import Queue q = Queue.Queue() q.qsize() #获取Queue的大小
q.empty() #是否为空,是则返回True,否则返回False
q.full() #是否已满,是则返回True,否则返回False
q.put(item[, block[, timeout]]) #put元素到Queue中,可选参数block默认值为True,timeout默认值为None,即为阻塞方法,
#接上,若timeout为正值,则代表会阻塞timeout的时长之后引发一个full的异常(如果已满)
q.put_nowait(item) #相当于q.put(item, False)
q.get([block[, timeout]]) #get元素到Queue中,可选参数block默认值为True,timeout默认值为None,即为阻塞方法,
#接上,若timeout为正数,则代表会则色timeouu的时长之后会引发一个empty的异常(如果为空)
q.get_nowait() #相当于q.get(False)
q.task_done() #用在Queue的消费者模式下,即用在Queue.get()方法之后,通过Queue.task_done()告诉Queue当前任务完成
#如果当前join正在阻塞,则它将在所有item都被处理之后恢复
q.join() #会保持阻塞直到队列中的所有item都会处理
#接上,未完成的task数目会增加当一个item被add到Queue中,未完成的task数目会降低,每当消费者线程调用task_done来表示所有的
#接上,work都完成了,当未完成的数目降低到0时,join就自动取消阻塞了

Queue的主要用法是什么?

看一下Queue的源码实现,然后在另一篇博客中更新一下。

#coding=utf-8

"""
理解Queue的用法,理解Queue衍生出来的不同的class
""" from Queue import Queue
from threading import Thread
import time
import random q = Queue() class producerQueue(Thread):
def __init__(self, queue):
Thread.__init__(self)
self.queue = queue def run(self):
while True:
r = random.randint(0, 99)
self.queue.put(r)
print self.getName() + "produce " + str(r)
time.sleep(1) class consumerQueue(Thread):
def __init__(self, queue):
Thread.__init__(self)
self.queue = queue def run(self):
while True:
r = self.queue.get()
print self.getName() + "consume " + str(r)
time.sleep(3)
self.queue.task_done() if __name__ == "__main__":
threads = []
for i in range(5):
t = producerQueue(q)
t.start()
# threads.append(t) for i in range(3):
t = consumerQueue(q)
t.start()
# threads.append(t) q.join()

之后得到的结果如下:

python——线程相关的更多相关文章

  1. python线程池ThreadPoolExecutor(上)(38)

    在前面的文章中我们已经介绍了很多关于python线程相关的知识点,比如 线程互斥锁Lock / 线程事件Event / 线程条件变量Condition 等等,而今天给大家讲解的是 线程池ThreadP ...

  2. Python之路(第四十二篇)线程相关的其他方法、join()、Thread类的start()和run()方法的区别、守护线程

    一.线程相关的其他方法 Thread实例对象的方法 # isAlive(): 返回线程是否活动的. # getName(): 返回线程名. # setName(): 设置线程名. ​ threadin ...

  3. python——线程与多线程进阶

    之前我们已经学会如何在代码块中创建新的线程去执行我们要同步执行的多个任务,但是线程的世界远不止如此.接下来,我们要介绍的是整个threading模块.threading基于Java的线程模型设计.锁( ...

  4. Python 线程、进程和协程

    python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点,在threading 得到了弥补,为了不浪费时间,所以我们直接学习threading 就可以了. ...

  5. [python] 线程简介

    参考:http://www.cnblogs.com/aylin/p/5601969.html 我是搬运工,特别感谢张岩林老师! python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件 ...

  6. Python线程指南

    本文介绍了Python对于线程的支持,包括“学会”多线程编程需要掌握的基础以及Python两个线程标准库的完整介绍及使用示例. 注意:本文基于Python2.4完成,:如果看到不明白的词汇请记得百度谷 ...

  7. 进程 & 线程相关知识

    不管Java,C++都有进程.线程相关的内容.在这里统一整理吧. Python的线程,其实是伪线程,不能真正的并发.下面也有讲. 线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序 ...

  8. Python线程

    原文出处: AstralWind 1. 线程基础 1.1. 线程状态 线程有5种状态,状态转换的过程如下图所示: 1.2. 线程同步(锁) 多线程的优势在于可以同时运行多个任务(至少感觉起来是这样). ...

  9. Python 线程,进程

    Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元 线程不能实现多并发 只能实现伪并发 每次工作 只能是一个线程完成 由于python解释器 原生是c  原生线程 底层都会有一把 ...

随机推荐

  1. VSFTP 服务器配置

    解决root用户无法登陆ftp传输文件的问题 配置vsftpd用户,启用root用户.  #cd /etc/vsftpd #vi ftpusers  注释掉root  修改user_list文件  # ...

  2. as2 attachMovie库影片无法获取其影片里面的对象或方法

    1.attachMovie的容器有两个,导致出错.举例子.创建了一个空的gameMc,然后容器又new个同个名字的,在这里不知道为什么不会替换,而是叠加 containerGame.createEmp ...

  3. Windows下MongoDB安装配置

    一.安装 官网下载,一般选择community server版本下载,如果是企业可以选择enterprise版本,个人使用的话community就可以了,附上链接:https://www.mongod ...

  4. PRC远程过程调用

    RPC(Remote Promote Call) 一种进程间通信方式.允许像调用本地服务一样调用远程服务. RPC框架的主要目标就是让远程服务调用更简单.透明.RPC框架负责屏蔽底层的传输方式(TCP ...

  5. 如何安装和配置RabbitMQ(转载)

    如何安装和配置RabbitMQ 今天开始一个小小的练习,学习一下安装和配置RabbitMQ,为什么要学它,因为WCF可以完全兼容和使用RabbitMQ了.我们新的大数据系统需要使用消息队列,所以就开始 ...

  6. 简单几步手工扩容LVM(笔记)

    参考文档:https://www.cnblogs.com/einyboy/archive/2012/05/31/2528661.html 1.查看磁盘是否被系统认出: fdisk -l 如显示加的磁盘 ...

  7. iframe多窗口

    Window 对象 浏览器会在其打开一个 HTML 文档时创建一个对应的 window 对象.但是,如果一个文档定义了一个或多个框架(即,包含一个或多个 frame 或 iframe 标签),浏览器就 ...

  8. Hibernate学习笔记2.3(Hibernate基础配置)

    映射,注释可以放在成员变量上面,也可以放在get方法上面 写在成员变量的话 破坏了java的面向对象思维 直接让hibernate访问内部的私有元素 要是能直接设指不合适哈哈 所以主张写在get方法上 ...

  9. Docker 批量启动

    批量配置IP for i in `docker ps -a|awk 'NR>1 {print $NF}'`;do IP=`echo $i|awk -F_ '{print "192.16 ...

  10. 2017面向对象程序设计(Java)第2周学习指导及要求(2017.8.28-2017.9.3)

    学习目标 继续适应老师教学方式的变化,能按照翻转课堂教学要求完成课前知识学习: 掌握Java Application程序结构: 掌握Java的数据类型与变量: 学会使用运算符构造各类表达式: 掌握输入 ...