您的位置:首页 > 编程语言 > Python开发

python多线程

2017-10-18 02:35 204 查看
上回使用情况用到了线程,那时候直接copy别人的代码,然后针对自己问题改了下代码。今天有空学习下python的线程。

发现参考的博客:http://www.cnblogs.com/huxi/archive/2010/06/26/1765808.html

文章绝大部分内容来自:

《Python参考手册 第4版》:https://item.jd.com/12052200.html

在linux中的线程就是进程中的一个执行单元,可在进程中开多个线程。线程之间的资源可以共享。

使用多个线程时,主机操作系统主要负责安排他们工作。做法:给每个线程分配一个小的时间片,并在素有活动任务之间快速循环–给每个任务分配一部分可用的cpu周期。如:同时允许的10个活动线程,操作系统将给每个线程分配大约1/10的cpu时间,同时在线程之间快速循环。

但是如果有多个线程访问操作同一份资源呢?比方都将数据添加到文件中,而且也会删除其中部分数据,这就涉及到锁机制。

关于GIL的详细来历,请跳转这篇文章:

http://python.jobbole.com/81822/

从该文中得出的结论是,放弃多线程改用多进程。

但是多线程也有一定的适用场景:关键时候,那个解决问题用那个。

threading模块:提供Thread类和各种同步原语,用于多线程的程序。

Thread类用于表示单独的控制线程,下面可以创建一个线程:
Thread(group=None,target=None,name=None,args=(),kwargs{})
group=None ,为以后版本保留的
target是一个可调用对象,线程启动时,run()方法将调用此对象,它的默认值是None,表示不调用任何对象。
name是线程名称。默认将创建一个“Thread-N”格式的唯一名称。
args是传递给target给target函数的参数元组。
kwargs是传递给target的关键字参数的字典。
所以创建一个实例:
+++++++++++++++++++
import threading
def printName():
pass
t = threading.Thread(target=printName,args=('hexian',))
++++++++++++++
上面的只是一个简单的测
4000
试。


一旦创建了Thread的实例,它支持下面的方法和属性:

t.start():
通过在一个单独的控制线程中调用run方法,启动线程。此方法只能调用一次。

t.run():
线程启动时将调用此方法。默认,它将调用传递到调用函数中的目标函数。可以使用继承Thread的子类中重写该方法

t.join([timeout])
等待直到线程终止或者出现超时为止。timeout为浮点数,单位秒。线程启动之前,不能调用它。

t.is_alive():
判断线程是否活动,返回True或False.线程从start()开始,到run()结束之前都是活动的。t.isalive()该方法别名。

t.name:
属性,线程名称,线程名为唯一标识符。

t.ident:
属性,整数线程标识符。如果线程尚未启动,它的值为None.

t.daemon:
线程的布尔型后台标识。必须在调用start()方法之前设置这个标识,它的初始值从创建线程的后台状态继承而来。


如下面:

[root@VM_131_54_centos allTest]# cat th1.py
import threading
import time
def clockTime(interval):
x = 1
while x:
print "The time is %s"%time.ctime()
time.sleep(interval)
x = 0
t = threading.Thread(target=clockTime,args=(50,))
t.daemon = True
t.start()
print t.ident
print t.name

[root@VM_131_54_centos allTest]# python th1.py
The time is Wed Oct 18 00:20:03 2017
140491998664448
Thread-1
#当这种并不能出现sleep(50)的效果,这是因为t.daemon = True.
一旦设置为True,线程则永远在后台运行。设置daemon标志会使在主程序退出后立即退出。线程自然销毁。


而下面一种:

[root@VM_131_54_centos allTest]# cat th2.py
import threading
import time
def clockTime(interval):
x = 1
while x:
print "The time is %s"%time.ctime()
time.sleep(interval)
x = 0
t = threading.Thread(target=clockTime,args=(50,))
t.daemon = True
t.start()
[root@VM_131_54_centos allTest]# python th2.py
The time is Wed Oct 18 00:35:13 2017
[root@VM_131_54_centos allTest]# cat th1.py
import threading
import time
def clockTime(interval):
x = 1
while True:
print "The time is %s"%time.ctime()
time.sleep(interval)
x = 0
t = threading.Thread(target=clockTime,args=(50,))
t.start()
print t.ident
print t.name
#这一种的结果就是:执行后等待50后结束。


一般使用的时候会将一个线程定义一个类:

[root@VM_131_54_centos allTest]# cat th3.py
import threading
import  time

class ClockThread(threading.Thread):
def __init__(self,interval):
threading.Thread.__init__(self)
self.interval = interval
def run(self):
x = 1
while x:
print "the time is %s"%time.ctime()
time.sleep(self.interval)
x = 0
t = ClockThread(15)
t.start()
#等待15秒。


Timer对象:

Timer: 隔一定时间调用一个函数,如果想实现每隔一段时间就调用一个函数的话,就要在Timer调用的函数中,再次设置Timer。Timer是Thread的一个派生类

Timer(interval,func[,args[,kwargs]])
创建定时器对象后,在过去interval时间后,执行函数func.在调用start()方法后会启动定时器。
方法:
t.start()
t.cancel()
如果函数尚未执行,取消定时器。


Lock对象

互斥锁定,状态有两种,已锁定和未锁定。两个方法acquire()和release()用于修改锁定的状态。如果状态为锁定,尝试获取锁定将被阻塞,直到锁定被释放。如果有多个线程等待获取锁定,当锁定被释放时,只有一个线程能获取它。

注意:等待线程获取锁定的顺序没有定义。

使用下面的构造函数可以创建新的Lock实例
lk = Lock()
创建新的Lock对象,初始化为未锁定

Lock实例支持以下方法:
lk.acquire([blocking])
获取锁定,如果有必要,需要阻塞到获取锁定释放为止。如果提供blocking参数并将它设为False,当无法获取锁定时立即返回False,如果成功获取锁定返回True.

lk.release()
释放一个锁定。当锁定处于未锁定状态时,或者从与原本调用acquire()方法的线程不同的线程调用此方法,将出现错误。


RLock:可重入锁定

类似Lock,但是可以在内部可以执行嵌套acquire()和release()操作。

信号量与有边界的信号量。

信号量是一个基于计数器的同步原语。每次调用acquire()方法时此计数器减1,每次调用release方法时此计数器加1。如果计数器为0,acquire()方法将会阻塞,直到其他线程调用release()方法为止。

Semaphore([value])
创建一个新的信号量。value是计数器的初始值。如果省略此参数,计数器的值将被置1。
s = Semaphore()
s.acquire([blocking])
获取信号量,如果进入时内部计数器大于0,此方法将它减1,然后立即返回。如果为0,阻塞,直到另一线程release()。
s.release()

BoundedSemaphore([value]):
创建新的信号机。value为计数器的初始值。默认为1。


信号机和互斥锁之间的差别:信号机能发信号。例如:可以从不同线程调用acquire()和release()方法,以便在生产者和使用者线程之间进行通信。

事件

事件用于线程之间通信。一个线程发出“事件”信号,一个或多个其他线程等待它。

+++++++++++++++++++++更新+++++++++++++

Threading模块:



thread类的实例方法:



守护线程

守护线程:一旦这是某一线程为守护线程,那么该线程不重要,如果你的进程要结束了,不用等待这个线程退出。


直接附上来源链接:

http://blog.csdn.net/u012063703/article/details/51601579

import time
import threading

def fun():
print "start fun"
time.sleep(2)
print "end fun"

print "main thread"
t1 = threading.Thread(target=fun,args=())
t1.setDaemon(True)
t1.start()
time.sleep(1)
print "main thread end"


线程锁

构造方法:

Lock()

实例方法:

acquire([timeout]): 使线程进入同步阻塞状态,尝试获得锁定。

release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。

from time import sleep, ctime
import threading
import threading
import random

threads = []
loops = [2,10]
t = []
mutex = threading.Lock()

class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global t,mutex
if mutex.acquire():
a = int(random.random()*10)
if a not  in t and len(t) <=10:
t.append(a)
print t
mutex.release()
else:
print t
mutex.release()
def test():
for x in range(10):
t = MyThread()
threads.append(t)
for x in range(len(threads)):
threads[x].start()

for x in range(10):
print threads[x].isAlive()
if __name__ == "__main__":
test()


输出结果:

[root@VM_131_54_centos pachong]# python threadtest.py
[9]
[9, 8]
[9, 8, 3]
[9, 8, 3]
[9, 8, 3, 2]
[9, 8, 3, 2]
[9, 8, 3, 2, 6]
[9, 8, 3, 2, 6]
[9, 8, 3, 2, 6]
[9, 8, 3, 2, 6]
False
False
False
False
False
False
False
False
False
False


待完善。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python