Python中创建线程有两种方式:函数或者用类来创建线程对象。

  • 函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。
  • 类:创建threading.Thread的子类来包装一个线程对象。

一.函数式:调用thread模块中的start_new_thread()函数来产生新线程

thread.start_new_thread ( function, args[, kwargs] )
  • function - 线程函数
  • args - 传递给线程函数的参数,他必须是个tuple类型
  • kwargs - 可选参数

例:通过thread来创建新线程

import thread,time

def timer(name,delay):
count = 0
while count < 5:
time.sleep(delay)
count +=1
print "%s:%s" %(name,time.ctime()) #创建两个线程
thread.start_new_thread(timer,('Thread-1',2,)) #timer表示执行timer函数,后面元组内表示timer函数的两个参数
thread.start_new_thread(timer,('Thread-2',4,))
while 1:
pass

输出结果:

Thread-1:Tue Oct 18 16:05:23 2016
Thread-1:Tue Oct 18 16:05:25 2016
Thread-2:Tue Oct 18 16:05:25 2016
Thread-1:Tue Oct 18 16:05:27 2016
Thread-1:Tue Oct 18 16:05:29 2016
Thread-2:Tue Oct 18 16:05:29 2016
Thread-1:Tue Oct 18 16:05:31 2016
Thread-2:Tue Oct 18 16:05:33 2016
Thread-2:Tue Oct 18 16:05:37 2016
Thread-2:Tue Oct 18 16:05:41 2016

二.类:创建threading.Thread的子类来包装一个线程对象

例1,通过threading来创建新线程:

import threading,time

def show(arg):
time.sleep(2)
print 'thread' + str(arg) for i in range(10):
t = threading.Thread(target=show,args=(i,)) #target=show执行show函数,后面args表示show函数中传入的参数
t.start()

运行结果:

Main thread stop.
Tue Oct 18 11:44:41 2016
thread0
thread2
thread4
thread3
thread1
thread8
thread6
thread5
thread7
thread9

 

例2:单线程

from time import ctime,sleep
def Music(music):
for i in range(2):
print ('I am listening to the music now...%s' %ctime())
sleep(2) def Movie(movie):
for i in range(2):
print('I am watching movie now...%s' %ctime())
sleep(5) if __name__ == '__main__':
Music('Goodbye')
Movie('Who Am I')
print ('Main Process is over...%s' %ctime())

输出结果:

I am listening to the music now...Mon Dec 12 14:53:24 2016
I am listening to the music now...Mon Dec 12 14:53:26 2016
I am watching movie now...Mon Dec 12 14:53:28 2016
I am watching movie now...Mon Dec 12 14:53:33 2016
Main Process is over...Mon Dec 12 14:53:38 2016

例3:多线程

import threading
import time def Music(music):
for i in range(2):
print('I am listening to the <%s> now...%s' %(music,time.ctime()))
time.sleep(2) def Movie(movie):
for i in range(2):
print('I am watching <%s> now...%s' %(movie,time.ctime()))
time.sleep(5) t1 = threading.Thread(target=Music,args=('I Will',))
t2 = threading.Thread(target=Movie,args=('The Walking Dead',)) if __name__ == '__main__':
#t1.daemon = True #如果为True,说明该线程为守护线程,也就表明这个线程不重要,在主线程退出的时候不用等待这个线程
#t2.daemon = True
#如果想等待子线程执行完之后,主线程才退出,就不需要设置daemon属性(daemon属性默认就为False)
t1.start()
t2.start()
#t1.join() #停止主线程,直到执行完子线程t1后才执行主线程
#t2.join() #停止主线程,直到执行完子线程t2后才执行主线程
print('all is over...%s' %time.ctime())

输出结果:

I am listening to the <I Will> now...Mon Dec 12 14:41:48 2016   #与另外一条子线程同时运行的,注意时间!
I am watching <The Walking Dead> now...Mon Dec 12 14:41:48 2016
all is over...Mon Dec 12 14:41:48 2016
I am listening to the <I Will> now...Mon Dec 12 14:41:50 2016
I am watching <The Walking Dead> now...Mon Dec 12 14:41:53 2016

上面例题中如果启用t1.join和t2.join结果如下:

I am listening to the <I Will> now...Mon Dec 12 14:42:56 2016
I am watching <The Walking Dead> now...Mon Dec 12 14:42:56 2016
I am listening to the <I Will> now...Mon Dec 12 14:42:58 2016
I am watching <The Walking Dead> now...Mon Dec 12 14:43:01 2016
all is over...Mon Dec 12 14:43:06 2016 #等待子线程运行结束后才执行主线程

Threading模块中所有对象:

1,Thread

  • start() #开始线程的执行
  • run() #定义线程的功能的函数(一般会被子类重写)
  • join(timeout=None) #程序挂起,直到该线程执行结束(如果设置了timeout,最多阻塞timeout秒)
  • getName() #返回线程名字
  • setName(name) #设置线程名字
  • isAlive() #查看该线程是否还在运行
  • isDaemon(False) #设置守护进程(True)或非守护线程(默认为False),如果设置为守护线程(True)表示该线程不重要,主线程无需等待该线程结束才退出。

2,Lock(Rlock):只允许一个线程更改数据。提供acquire方法(获取锁)和release方法(释放锁)

  • RLock和Lock 的区别:RLock允许在同一线程中被多次acquire和release。RLock中acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。而Lock不一样,同一线程只能使用一次acquire和release方法。

3,condition

4,Event

5,Semaphore(BoundedSemaphore):同时允许一定数量的线程更改数据,信号量也提供acquire方法和release方法。

6,其他函数:

activeCount() #返回当前活动线程的数量
currentThread() #返回当前线程
enumerate() #返回当前活动线程的列表
settrace(func) #为所有线程设置一个跟踪函数
setprofile() #为所有线程设置一个profile函数

多线程实现同步的方法:

1.线程锁:在同一个进程中的资源,所有线程都是共享的。线程之间是进行随机调度,如果不同线程同时对数据进行修改,就会产生问题。为了保证数据的准确性,引入了锁的概念。也就是在同一时刻只允许一个线程操作该数据。

锁有两种状态:锁定和未锁定

每当一个线程1要访问共享数据时,必须先获得锁定;如果已经有别的线程2获得锁定了,那么就让线程1暂停,也就是同步阻塞;等到线程2访问完毕,释放锁以后,再让线程1继续。

使用锁方法:

lock = threading.Lock()   #创建锁
lock.acquire([timeout]) #锁定
lock.release() #释放

例1:未使用锁之前:(注意同一时间点,num值的变化)

import threading
import time num = 0 def fun(arg):
global num
time.sleep(1)
num += 1
print(num,'-->','%s'%time.ctime()) for item in range(5): #开启5个子线程
t = threading.Thread(target=fun,args=(item,))
t.start() print('Main threading stop !')

输出结果:

Main threading stop !
1 --> Mon Dec 12 15:51:03 2016
2 --> Mon Dec 12 15:51:03 2016
3 --> Mon Dec 12 15:51:03 2016 #同一时间点输出的num都不一样
4 --> Mon Dec 12 15:51:03 2016
5 --> Mon Dec 12 15:51:03 2016

例2:使用锁之后:

import threading
import time num = 0
lock = threading.Lock() #创建锁 def fun(arg):
lock.acquire() #获取锁
global num
time.sleep(1)
num += 1
print(num,'-->','%s'%time.ctime())
lock.release() #释放锁 for item in range(5): #开启5个子线程
t = threading.Thread(target=fun,args=(item,))
t.start() print('Main threading stop !')

输出结果:

Main threading stop !
1 --> Mon Dec 12 15:56:34 2016
2 --> Mon Dec 12 15:56:35 2016
3 --> Mon Dec 12 15:56:36 2016 #注意:同一时间点num值不变
4 --> Mon Dec 12 15:56:37 2016
5 --> Mon Dec 12 15:56:38 2016

2,信号量Semaphore

例:

import threading
import time se = threading.Semaphore(5) #同时允许5个线程修改数据 def fun(n):
se.acquire()
time.sleep(1)
print('thread:%s -->%s'%(n,time.ctime()))
se.release() if __name__ == '__main__':
for i in range(10):
t = threading.Thread(target=fun,args=(i,))
t.start()

输出结果:

thread:0 -->Mon Dec 12 16:36:12 2016
thread:1 -->Mon Dec 12 16:36:12 2016
thread:3 -->Mon Dec 12 16:36:12 2016
thread:2 -->Mon Dec 12 16:36:12 2016
thread:4 -->Mon Dec 12 16:36:12 2016 #同一时间点,允许5个线程同时修改值
thread:6 -->Mon Dec 12 16:36:13 2016
thread:8 -->Mon Dec 12 16:36:13 2016
thread:5 -->Mon Dec 12 16:36:13 2016
thread:9 -->Mon Dec 12 16:36:13 2016
thread:7 -->Mon Dec 12 16:36:13 2016

3,时间event:通用的条件变量,多个线程可以等待某个事件发生后,所有线程都被激活。事件主要提供了三个方法 set、wait、clear。

事件处理的机制:

全局定义了一个“Flag”:
(1)如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞
(2)如果“Flag”值为True,那么event.wait 方法时便不再阻塞

clear:将“Flag”设置为False
set:将“Flag”设置为True

import threading

eve = threading.Event()

def fun(e):
print('start...')
e.wait()
print('execute...') for i in range(5):
t = threading.Thread(target=fun,args=(eve,))
t.start() eve.clear()
usr_input = input('Enter the flag:')
if usr_input =='':
eve.set()

输出结果:

start...
start...
start...
start...
start...
Enter the flag:1
execute...
execute...
execute...
execute...
execute...

4,条件Condition:使线程进入等待状态,当满足某个条件时,才释放线程。

notify()方法会唤醒一个在等待conditon变量的线程;notify_all() 则会唤醒所有在等待conditon变量的线程

例如生产者模型:

import threading
import time
c = threading.Condition() def fun(n):
c.acquire()
c.wait()
print('current threading:%s ---> %s' %(n,time.ctime()))
time.sleep(1)
c.release() if __name__ == '__main__':
for i in range(10):
t = threading.Thread(target=fun,args=(i,))
t.start() while True:
usr_input = input('Enter:')
if usr_input == 'q':
break c.acquire()
c.notify(int(usr_input))
c.release()

输出结果:

Enter:3
current threading:1 ---> Mon Dec 12 17:14:40 2016
current threading:2 ---> Mon Dec 12 17:14:41 2016
current threading:0 ---> Mon Dec 12 17:14:39 2016
current threading:0 ---> Mon Dec 12 17:14:39 2016
Enter:5
current threading:4 ---> Mon Dec 12 17:14:47 2016
current threading:6 ---> Mon Dec 12 17:14:48 2016
current threading:3 ---> Mon Dec 12 17:14:49 2016
current threading:5 ---> Mon Dec 12 17:14:50 2016
current threading:7 ---> Mon Dec 12 17:14:51 2016
Enter:3
current threading:9 ---> Mon Dec 12 17:14:59 2016
current threading:8 ---> Mon Dec 12 17:15:00 2016
Enter:q Process finished with exit code 0

5.定时器:指定n秒后执行某操作

import threading
import time print('Time:%s'%time.ctime())
def Print():
print('hello,python...%s'%time.ctime()) t = threading.Timer(2,Print) #2秒后执行Print函数
t.start()

输出结果:

Time:Mon Dec 12 17:24:50 2016
hello,python...Mon Dec 12 17:24:52 2016 #2秒后执行

同步队列Queue:

  • Queue模块提供了同步队列和线程安全。包括FIFO队列、LIFO队列以及优先级队列。可以使用队列来实现线程间的同步。

    FIFO:(默认为FIFO)

  • Queue模块可以用来进行线程间通讯,让各个线程之间共享数据。
  • Queue解决了生产者,消费者的问题。

Queue模块常用方法:

import queue  #导入queue模块
q = queue.Queue(maxsize=0) #构造一个FIFO队列。maxsize指定队列的长度。为0时,表示队列长度无限制。 q.put(item='n',block=1,timeout=None) #在队尾插入一个item(必选项)。如果当前队列为空,且block为1(默认值)时,put()方法就使
#线程暂停,一直阻塞到队列中有空间为止;如果block为0,put()方法会引发Full异常。 q.get(block=1,timeout=None) #从队首删除并返回一个项目。当block为1(默认值)时,get()方法使线程暂停,直到有项目可用。如果队列为空,且block为0时,队列将引发empty异常。 q.put_nowait(item='n') #相当于q.put(item,False)
q.get_nowait() #相当于q.get(False)
q.join() #等到队列为空时,在执行别的操作
q.qsize() #返回队列的大小
q.empty() #当队列为空时,返回True,否则返回False
q.full() #当队列满时,返回True,否则返回False
q.task_done() #在完成一项工作之后,它向任务已完成的队列发送一个信号

例:

from threading import Thread
from queue import Queue
import time class Producer(Thread): #定义生产者类
def __init__(self,name,queue):
self.Name = name
self.Queue = queue
super(Producer,self).__init__() #执行父类的构造函数 def run(self): #生产者具体工作内容
while True:
if self.Queue.full():
time.sleep(1)
else:
self.Queue.put('产品')
time.sleep(1)
print ('%s生产一个产品' %(self.Name,)) #Thread.run(self) class Consumer(Thread): #定义消费者类
def __init__(self,name,queue):
self.Name = name
self.Queue = queue
super(Consumer, self).__init__() #执行父类的构造函数
def run(self):
while True:
if self.Queue.empty():
time.sleep(1)
else:
self.Queue.get('产品')
time.sleep(1)
print ('%s消费了一个产品' %(self.Name,))
#Thread.run(self) que = Queue(maxsize=100) #定义容器 person1 = Producer('P1',que) #创建生产者P1
person1.start()
person2 = Producer('P2',que) #创建生产者P2
person2.start()
person3 = Producer('P3',que) #创建生产者P3
person3.start() for num in range(20): #创建消费者20人:C1,C2...C20
name = 'C1%d' %(num,)
item = Consumer(name,que)
item.start()

Python:线程的更多相关文章

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

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

  2. python——线程与多线程基础

    我们之前已经初步了解了进程.线程与协程的概念,现在就来看看python的线程.下面说的都是一个进程里的故事了,暂时忘记进程和协程,先来看一个进程中的线程和多线程.这篇博客将要讲一些单线程与多线程的基础 ...

  3. [python] 线程简介

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

  4. PYTHON线程知识再研习A

    前段时间看完LINUX的线程,同步,信息号之类的知识之后,再在理解PYTHON线程感觉又不一样了. 作一些测试吧. thread:模块提供了基本的线程和锁的支持 threading:提供了更高级别,功 ...

  5. Python 线程(threading) 进程(multiprocessing)

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  6. Python线程:线程的调度-守护线程

    Python线程:线程的调度-守护线程   守护线程与普通线程写法上基本么啥区别,调用线程对象的方法setDaemon(true),则可以将其设置为守护线程.在python中建议使用的是thread. ...

  7. python 线程(一)理论部分

    Python线程 进程有很多优点,它提供了多道编程,可以提高计算机CPU的利用率.既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的. 主要体现在一下几个方面: 进程只能在 ...

  8. python线程同步原语--源码阅读

    前面两篇文章,写了python线程同步原语的基本应用.下面这篇文章主要是通过阅读源码来了解这几个类的内部原理和是怎么协同一起工作来实现python多线程的. 相关文章链接:python同步原语--线程 ...

  9. Python学习——Python线程

    一.线程创建 #方法一:将要执行的方法作为参数传给Thread的构造方法 import threading import time def show(arg): time.sleep(2) print ...

  10. Python 线程和进程和协程总结

    Python 线程和进程和协程总结 线程和进程和协程 进程 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间.内存等)的基本单位: 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其 ...

随机推荐

  1. IE8 jq focus BUG

    jq的 .focus() 在IE8下面会有一些意想不到的BUG,下面是解决办法: 一.我做的项目中有些场景需要用到键盘的回车作为触发事件,然后把focus移到其他功能或者按钮上面,刚刚好这个按钮或者功 ...

  2. windows下git识别大小写配置

    默认情况下windows上的Git客户端,在文件名仅发生大小写改变时不会识别,提交后发现,gitlab上的文件名不会发生变化. 解决方法: 编辑 .git 中的config文件, 将 ignoreca ...

  3. arcgis将图片转成shp地图

    打开arcMap 1.右键[图层]-[属性]-[坐标系]-[地理坐标系]-双击"WGS 1984" 2.右键[图层]-[添加数据],打开图片文件-Band_2 3.右键图片-[属性 ...

  4. .NET (一)委托第一讲:什么是委托

    1.为什么要使用委托? 生活中的委托就是委托他人帮我们去办一件事情,程序中的委托类似.看下面的例子 class Class1 { static void Main(String[] args) { L ...

  5. .NET ORM工具Pax实战

    Pax是微软的一个ORM读写工具,比NHibernate更好用.可以在项目中用Nuget下载并安装. 可以看到引用中多了 在App.config里设置配置文件如下 <?xml version=& ...

  6. PHPCMS V9 分页类的修改教程

    首先,打开 phpcms\libs\functions\global.func.php 这个文件,找到文件第622行的分页函数,复制一下,粘贴到默认分页函数的下面,重新命名后保存.(笔者在此命名为:p ...

  7. EUI Scroller实现图片轮播 组件 ItemScroller

    一 自定义组件如下 /** * 文 件 名:ItemScroll.ts * 功 能: 滚动组件 * 内 容: 自定义组件,支持多张图片水平(垂直)切换滚动 * * Example: * 1. 从自定义 ...

  8. 操作系统 页面置换算法LRU和FIFO

    LRU(Least Recently Used)最少使用页面置换算法,顾名思义,就是替换掉最少使用的页面. FIFO(first in first out,先进先出)页面置换算法,这是的最早出现的置换 ...

  9. Patching Array

    引用原文:http://blog.csdn.net/murmured/article/details/50596403 但感觉原作者的解释中存在一些错误,这里加了一些自己的理解 Given a sor ...

  10. Python 多线程 Condition 的使用

    Condition Condition(条件变量)通常与一个锁关联.需要在多个Contidion中共享一个锁时,可以传递一个Lock/RLock实例给构造方法,否则它将自己生成一个RLock实例. 可 ...