标签:判断 队列 用户 空间 join() 保护 标识 子线程 time
进程,是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竟争计算机系统资源的基本单位。每一个进程都有一个自己的地址空间,即进程空间或(虚空间)。进程空间的大小 只与处理机的位数有关,一个 16 位长处理机的进程空间大小为 216 ,而32 位处理机的进程空间大小为 232 。进程至少有 5 种基本状态,它们是:初始态,执行态,等待状态,就绪状态,终止状态。
线程,在网络或多用户环境下,一个服务器通常需要接收大量且不确定数量用户的并发请求,为每一个请求都创建一个进程显然是行不通的,——无论是从系统资源开销方面或是响应用户请求的效率方面来看。因此,操作系统中线程的概念便被引进了。线程,是进程的一部分,一个没有线程的进程可以被看作是单线程的。线程有时又被称为轻权进程或轻量级进程,也是 CPU 调度的一个基本单位。
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对
其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一
个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但
对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
在进程上加一把锁,为了锁住多个线程,只要多个线程中的其中一个去访问了CPU,那么久锁住进程的资源,不允许其他线程访问同一资源
setDaemon(True):主线程不等待子线程
join(n):主线程最多等待子线程n秒
import threading
import time
def f1(a1, a2):
time.sleep(5)
print(‘666‘)
t1 = threading.Thread(target=f1, args=(123, 111))
t1.start()
t2 = threading.Thread(target=f1, args=(123, 111))
t2.start()
t3 = threading.Thread(target=f1, args=(123, 111))
t3.start()
‘‘‘
程序等待5秒后,3个线程同时输出666
实现并发
‘‘‘
import threading
import time
globals_num = 0
lock = threading.RLock() # 实例化一个锁
def Func():
lock.acquire() # 获得锁,锁定当前访问资源
global globals_num
globals_num += 1
time.sleep(1)
print(globals_num)
lock.release() # 释放锁,释放当前访问的资源
for i in range(10):
t = threading.Thread(target=Func)
t.start()
‘‘‘
休息一秒 输出一个,因为资源被锁定,
只能等资源被释放了才能使用全部变量
不能像上一个例子一样并发
‘‘‘
Event是线程间通信最间的机制之一:一个线程发送一个event信号,其他的线程则等待这个信号。
用于主线程控制其他线程的执行。 Events 管理一个flag,这个flag可以使用set()设置成True或者
使用clear()重置为False,wait()则用于阻塞,在flag为True之前。flag默认为False。
Event.wait([timeout]) : 堵塞线程,直到Event对象内部标识位被设为true或超时(如果提供了参数timeout)。
Event.set() :将标识位设为ture。
Event.clear() : 将标识伴设为false。
Event.isSet() :判断标识位是否为ture。
import threading
def do(event): # 循环生成了10个线程
print(‘start‘)
event.wait() # 线程产生阻塞,默认为flase,等待标志位为true,线程才继续执行
print(‘execute‘)
event_obj = threading.Event()
for i in range(10):
t = threading.Thread(target=do, args=(event_obj,))
t.start()
event_obj.clear() #falge设置为false
inp = input(‘input:‘)
if inp == ‘true‘:
event_obj.set() # flage设置为true
#创建进程
import multiprocessing
import time
# 主进程的主线程创建了两个子进程,再由子进程的线程去执行f1方法
def f1(a1):
time.sleep(2)
print(a1)
if __name__ == ‘__main__‘:
t1 = multiprocessing.Process(target=f1, args=(11,))
# t1.daemon = True
t1.start() # 运行进程 在Windows下需要写在__name__ == ‘__main__‘下
# t1.join()
t2 = multiprocessing.Process(target=f1, args=(11,))
# t2.daemon = True
t2.start()
print(‘end‘)
进程:
# 进程不能共享数据,拷贝原数据并单独使用
import multiprocessing
li = []
def foo(i):
li.append(i)
print(‘say hi‘,li)
if __name__ == ‘__main__‘:
for i in range(10):
p = multiprocessing.Process(target=foo, args=(i,))
p.start()
‘‘‘
say hi [1]
say hi [2]
say hi [0]
say hi [3]
say hi [4]
say hi [5]
say hi [6]
say hi [7]
say hi [8]
say hi [9]
‘‘‘
线程:
#线程与线程之间的内存是共享的
import threading
li = []
def foo(i):
li.append(i)
print(‘say hi‘,li)
if __name__ == ‘__main__‘:
for i in range(10):
p = threading.Thread(target=foo, args=(i,))
p.start()
‘‘‘
say hi [0]
say hi [0, 1]
say hi [0, 1, 2]
say hi [0, 1, 2, 3]
say hi [0, 1, 2, 3, 4]
say hi [0, 1, 2, 3, 4, 5]
say hi [0, 1, 2, 3, 4, 5, 6]
say hi [0, 1, 2, 3, 4, 5, 6, 7]
say hi [0, 1, 2, 3, 4, 5, 6, 7, 8]
say hi [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
‘‘‘
# manage.dict()共享数据 特殊的字典,支持进程之间共享数据
from multiprocessing import Process, Manager
def Foo(i, dic):
dic[i] = 100 + i
for k, v in dic.items():
print(k, v)
if __name__ == ‘__main__‘:
manage = Manager()
dic = manage.dict()
# dic = {}
for i in range(2):
p = Process(target=Foo, args=(i, dic))
p.start()
p.join() # 避免主进程关闭后,子进程无法连接主进程,无法拿到数据
print(dic)
‘‘‘
用manage.dict,数据共享
0 100 第一次只有1个数据
0 100 第二次有两个数据哟
1 101
{0: 100, 1: 101}
‘‘‘
‘‘‘
用普通字典,数据不共享
0 100
1 101
{}
‘‘‘
进程池:python内部提供
# python提供了进程池
from multiprocessing import Pool
import time
def Foo(i):
time.sleep(2)
print(i)
if __name__ == ‘__main__‘:
pool = Pool(5) # 最大能装5个进程,用一个加一个,不事先全部创完
# 申请进程,执行完后放回进程池
# pool.apply(Foo,(1,))
# pool.apply_async(func=Foo, args=(i,)).get() 执行完后,告诉我们一下,再放回进程池
# 执行完Foo方法后,将Foo方法的返回值,赋值给Bar方法的参数
# Bar方法,我们称之为回调函数
for i in range(40):
# pool.apply(Foo,(i,)) apply申请的时候,一个一个申请并执行
pool.apply_async(func=Foo, args=(i,)) # 并发进行,还能设置回调函数
print(‘666666666666‘)
pool.close()
pool.join()
low版线程池:缺点在于,线程执行任务后,不能被重复使用,会等待python销毁它
import queue
import threading
import time
class ThreadPool(object):
def __init__(self, max_num=20):
self.queue = queue.Queue(max_num) # 创建一个最大长度为20的队列
for i in range(max_num):
self.queue.put(threading.Thread) # 传递类名,有20个类名的队列,都指向同一个类
def get_thread(self):
return self.queue.get() # 当队列为空的时候,get则等待
def add_thread(self):
self.queue.put(threading.Thread)
def func(pool, a1):
time.sleep(1)
print(a1)
pool.add_thread()
p = ThreadPool(10)
for i in range(100):
thread = p.get_thread() # ret 等价于 threading.Thread,是个类名
t = thread(target=func, args=(p, i)) # 创建一个线程,将线程池对象传入func中,在func结束的时候,再将该线程重新放入线程池
t.start() # 启动线程
# 在队列中放类,线程放在内存在 等待销毁,这样是不合理的,我们可以优化,线程继续做第二件事情
# 在队列里面放任务,让线程不停的取任务,重复利用线程
标签:判断 队列 用户 空间 join() 保护 标识 子线程 time
原文地址:http://www.cnblogs.com/wuwen19940508/p/7096983.html