python线程与进程手记

228 阅读9分钟
-----------------------------线程---------------------------
#线程应用的第一种方式:thread模块是比较底层的模块
#import thread:引用的模块
#thread.start_new_thread(defName,()):线程的创建
#thread.exit_thread():线程的结束

#线程应用的第二种方式:threading模块是对thread做了一些包装,可以更方便被引用
#import threading:引用的模块
#myThread=threading.Thread(target=defName,args=('Alice',)):线程的创建
#myThread.start():线程开始执行
#num=len(threading.enumerate):线程数量的查看
#线程应用的第三种方式:创建一个线程类,继承基类:threading.Thread 。重写def run(self):方法。需要运行的内容,写在run方法里面。
#class MyThread(threading.Thread):创建类的对象
#可以进行重构函数的对应扩展:def __init__(self,name,time):threading.Thread.__init__(self,name='对应的线程名字')
#myThread=MyThread():创建对象
#myThread.start():线程开始执行
------------------------------线程同步之互斥锁---------------------------
#线程同步之互斥锁
#互斥锁同步:线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引用互斥锁。互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。
#mutex=threading.Lock():创建互斥锁
#if mutex.acquire([blocking]):互斥锁锁定状态,返回值不为0表示上锁成功
# 锁定方法acquire可以有一个blocking参数。如果设定blocking为True,则当前线程会堵塞,直到获取到这个锁为止(如果没有指定,那么默认为True);如果设定blocking为False,则当前线程不会堵塞
#mutex.release():互斥锁释放状态

------------------------------线程同步至可重入锁---------------------------
#线程同步之可重入锁
#RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次acquire。直到一个线程所有的acquire都被release,其他的线程才能获得资源:
#mutex=threading.RLock():创建可重入锁
#mutex.acquire():可重入锁锁定状态
#mutex.release():可重入锁释放状态
------------------------------线程同步之条件变量---------------------------
#线程同步之条件变量
#Python提供的Condition对象提供了对复杂线程同步问题的支持。Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。
#Condition对象维护了一个锁(Lock/RLock)和一个waiting池。线程通过acquire获得Condition对象,当调用wait方法时,线程会释放Condition内部的锁并进入blocked状态,同时在waiting池中记录这个线程。当调用notify方法时,Condition对象会从waiting池中挑选一个线程,通知其调用acquire方法尝试取到锁。
#Condition对象的构造函数可以接受一个Lock/RLock对象作为参数,如果没有指定,则Condition对象会在内部自行创建一个RLock。
#除了notify方法外,Condition对象还提供了notifyAll方法,可以通知waiting池中的所有线程尝试acquire内部锁。由于上述机制,处于waiting状态的线程只能通过notify方法唤醒,所以notifyAll的作用在于防止有线程永远处于沉默状态。
#con=threading.Condition():创建条件变量
#con.acquire():条件变量锁定状态
#con.wait():线程释放Condition内部的锁并进入blocked状态,同时在waiting池中记录这个线程
#con.notify():Condition对象会从waiting池中挑选一个线程,通知其调用acquire方法尝试取到锁
#con.notifyAll():唤醒所有处于waiting池中的所有线程,防止有线程永远处于沉默状态
#con.release():条件变量释放状态

------------------------------线程同步之队列---------------------------
#from Queue import Queue:进行对应的队列包的引用
#queue=Queue():队列的创建
#queue.qsize():获取队列中内容的数量
#queue.put(内容):向队列中添加对应的数据信息
#queue.set():从队列中取出对应的数据
#queue.empty():查看当前队列内容是否为空
[AppleScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
1 #引入对应的包
2 import threading
3
4 from Queue import Queue
5
6 from time import sleep
7
8 #线程生产者
9 class Producer(threading.Thread):
10 #重写run方法
11 def run(self):
12 global g_queue
13
14 while True:
15 if con.acquire():
16 #判断是否停止生产,获取队列中的数量
17 if g_queue.qsize() < 20:
18
19 #每次生产5个产品
20 for i in range(5):
21 g_queue.put("产品")
22
23 print("生产出5个产品,产品总量:%d"%g_queue.qsize())
24 else:
25 con.wait()
26 print("停止生产")
27
28 con.release()
29 sleep(1)
30
31
32 #线程消费者
33 class Consumer(threading.Thread):
34 #重写run方法
35 def run(self):
36 global g_queue
37
38 while True:
39 if con.acquire():
40 #判断是否停止消费
41 if g_queue.qsize()>5:
42 #进行消费
43 for i in range(3):
44 g_queue.get()
45
46 print("消费3 总数:%d"%g_queue.qsize())
47
48 if g_queue.qsize()<20:
49 con.notify()
50 con.release()
51 sleep(1)
52
53 #全局变量
54 con=threading.Condition()
55 #g_num=600
56 #创建一个队列
57 g_queue=Queue()
58
59
60 #main函数
61 def main():
62 pro=Producer()
63 pro.start()
64 con=Consumer()
65 con.start()
66
67 #程序入口
68 if __name__ == '__main__':
69 main()
------------------------------线程间通信---------------------------
threading.Event可以使一个线程等待其他线程的通知。其内置了一个标志,初始值为False。线程通过wait()方法进入等待状态,直到另一个线程调用set()方法将内置标志设置为True时,Event通知所有等待状态的线程恢复运行。还可以通过isSet()方法查询Envent对象内置状态的当前值。
#event=threading.Event():进行对应Envent对象的创建
#self.threadEvent=event :重构对应threading.Thread基类中的__init__的方法。
#self.threadEvent.wait():使线程进入等待状态
#event.set():启动waiting池中等待的线程

------------------------------线程的合并和后台线程---------------------------
python的Thread类中还提供了join()方法,使得一个线程可以等待另一个线程执行结束后再继续运行。这个方法还可以设定一个timeout参数,避免无休止的等待。因为两个线程顺序完成,看起来象一个线程,所以称为线程的合并。
默认情况下,主线程在退出时会等待所有子线程的结束。如果希望主线程不等待子线程,而是在退出时自动结束所有的子线程,就需要设置子线程为后台线程(daemon)。方法是通过调用线程类的setDaemon()方法。
#myThread.setDaemon(True):将该线程转为后台线程

------------------------------ThreadLocal---------------------------
global_dict={}
global_dict[threading.current_thread()]

------------------------------多进程---------------------------
在Unix/Linux操作系统中,提供了一个fork()系统函数,它非常特殊。
普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
子进程永远返回0,而父进程返回子进程的ID。
这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。
#import os :引用对应的进程包
#pid=os.fork():程序执行到os.fork()时,操作系统会创建一个新的进程(子进程),然后复制父进程的所有信息到子进程中,然后父进程和子进程都会从fork()函数中得到一个返回值,其进程中这个值一定是0,而父进程中是子进程的 id号
#os.getpid():获取当前进程的pid
#os.getppid():获取父进程的pid
------------------------------multiprocessing模块---------------------------
#from multiprocessing import Process:multiprocessing模块提供了一个Process类来代表一个进程对象。
#p=Process(target=run_proc,args=('test',)):创建对应的进程对象
#p.start():进程的启动
#p.join():multiprocessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束
#multiprocessing.cpu_count():查看对应的cpu核数
#pipe=multiprocessing.Pipe():创建一个管道,管道两个端口调用分别为pipe[0],pipe[1]
#pipe[0].send(i):为管道一侧进行内容的添加操作
#pipe[0].recv():获取管道一侧的内容信息
[AppleScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
1 #coding=utf-8
2
3 #引用对应的包
4 from socket import *
5
6 from multiprocessing import Process
7
8 import sys
9
10 #进程函数:为客户提供tcp服务
11 def tcpClient(newSocket,destAddr):
12 print("客户端(%s)以上线"%str(destAddr))
13 while True:
14 #数据的接受
15 recvData=newSocket.recv(1024)
16 #模拟echo将数据回发服务器
17 newSocket.send(recvData)
18
19 #如果接收的数据长度为0,进行客户端的关闭操作
20 if len(recvData) <= 0:
21 print("------客户端(%s)已经下线-------"%str(destAddr))
22
23 newSocket.close()
24 break
25 print ("客户端(%s)传递过的数据为:%s"%(str(destAddr),recvData))

更多技术资讯可关注:itheimaGZ获取