【python】进阶--->并发编程之线程(一)
在介绍进程之前,我先给大家补充一些 Queue() 和 进程池Pool 的概念
一、Queue()
Queue.put(item, block, timeout)
Queue.put_nowait(item)===>Queue.put(item, False)Queue.get(block, timeout):获取队列中的一条数据,然后将它从队列中移除
?如果block使用默认值True,且没有设置timeout秒,消息队列如果为空,那么程序将会被阻塞,直到从消息队列中读到消息为止
?如果block使用默认值True,设置timeout秒,则会等待timeout秒,若没有在这个时间内读取到数据,则会抛出异常queue.empty.
?如果block设置为False,消息队列为空,则会立即抛出异常queue.empty
Queue.get_nowait()===>Queue.get(False)Queue.empty() : 如果队列为空,返回True Queue.full():如果队列满了,返回True
Queue.qsize() : 返回当前队列包含的消息数量
import multiprocessing
import time
import random
# q = multiprocessing.Queue(3) # 括号内表示最多接收的消息数
# q.put('消息1')
# q.put('消息2')
# q.put('消息3')
# q.put('消息4', block=False) # 当队列满了之后,会阻塞,不能写入
# print(q.get())
# print(q.get())
# print(q.get())
# try:
# print(q.put('消息4'))
# except: # 捕捉异常
# print('消息队列为空')
# else:
# print('没有错误')
# if not q.empty():
# print(q.get())
def write(q):
for value in ['a', 'b', 'c']:
q.put(value)
time.sleep(random.random())
def read(q):
while True:
if not q.empty():
value = q.get()
print('获取%s' % value)
time.sleep(random.random())
else:
break
if __name__ == '__main__':
q = multiprocessing.Queue()
pw = multiprocessing.Process(target=write, args=(q, ))
pr = multiprocessing.Process(target=read, args=(q, ))
pw.start()
pw.join()
pr.start()
pr.join()
print('全部读写完成')
二、进程池Pool
multiprocessing.Pool() : 括号内可以传入最大可接受的进程数
常用函数 :
apply_async(func,args, kwargs) : 使用非阻塞方式调用func(并行执行, 阻塞 :必须等待上一个进程退出才能执行下一个进程),args和kwargs为传递给func的参数.
close() : 关闭进程池,不在接收新的进程 。
terminate() : 不管任务是否完成,立即终止.
join() : 主进程阻塞,等待子进程的退出,必须在调用close或者terminate后使用.
进程池中的Queue
如果要使用pool创建进程,就需要使用multiprocessing.Manager()中的Queue()
# import multiprocessing
# import time
#
#
# def run(f):
# time.sleep(1)
# return f*f
#
#
# if __name__ == '__main__':
# test1 = [1, 2, 3, 4, 5, 6]
# print('循序执行:')
# s = time.time()
# for i in test1:
# print(run(i))
# e1 = time.time()
# print('循序执行时间:', e1-s)
#
# print('并发:')
# pool = multiprocessing.Pool(5) # 创建拥有5条进程数量的进程池
# # map(函数,可迭代对象)
# # 循环将可迭代对象的值传给第一个参数的函数执行
# r1 = pool.map(run, test1)
# pool.close() # 关闭进程池,不再接收新的进程
# # pool对象调用join方法会等待所有子进程执行完毕
# # 但是调用之前必须调用close方法,表示不再接收新的进程
# pool.join()
# e2 = time.time()
# print('并发执行时间:', e2-e1)
# print(r1)
# 进程池中的进程通信
import multiprocessing, os, random, time
def read(q):
print('read启动(%s),父进程为(%s)' % (os.getpid(), os.getppid()))
for i in range(q.qsize()):
print('read从Queue中获取到消息:', q.get())
def write(q):
print('write启动(%s),父进程为(%s)' % (os.getpid(), os.getppid()))
for i in ['a', 'b', 'c', 'd']:
q.put(i)
print('write往Queue中写入消息:', i)
if __name__ == '__main__':
print('主进程(%s)启动' % os.getpid())
q = multiprocessing.Manager().Queue() # 使用Manager中的 Queue
pool = multiprocessing.Pool()
pool.apply_async(write, (q,))
time.sleep(1)
pool.apply_async(read, (q,))
pool.close()
pool.join()
print('主进程(%s)结束' % os.getpid())
三、线程
线程是进程的一个实体,是cpu调度和分配的基本单元.
线程自己基本上不拥有系统的资源,只拥有一点在运行中必不可少的资源,但是他和同属一个进程的其他线程共享进程所拥有的全部资源
例如:
进程 : 在一台电脑上运行的多个qq
线程 : 一个qq中的多个聊天窗口
区别 :
-
一个进程至少有一个线程,线程的划分尺度小于进程(资源比进程少)
-
进程在执行的过程中拥有独立的内存单元,而多个线程共享内存
-
线程不能独立执行,必须依存在进程中
threading.Thread(group, target, name, args, kwargs)
group : 线程组,目前没有用
target : 要执行的函数
name : 线程名,默认Thread-N
args/kwargs : 要传给函数的参数
常用方法:
is_alive() : 返回线程是否在运行
get/setName(name) : 获取/设置线程名
start() : 线程准备就绪,等待cpu调度
is/setDaemon(bool) : 获取/设置是守护线程(默认不是(False))
?如果是守护线程,主线程执行过程中,守护线程也在执行,主线程执行完毕后,不论守护线程是否成功执行完毕,都要停止.
?如果不是守护线程,主线程执行过程中,它也在执行,主线程执行完毕后,会等待该线程也执行完毕,才会结束程序.
join(timeout) : 阻塞当前上下文环境的线程,直到调用该方法的线程终止或者到达指定的timeout停止阻塞.
import time
import threading
def test():
print('hello')
time.sleep(1)
class MyThread(threading.Thread):
def run(self):
for i in range(5):
time.sleep(1)
print('hello')
if __name__ == '__main__':
s = time.time()
# for i in range(5):
# test()
# e = time.time()
# print('耗时:', e-s)
#
# for i in range(5):
# t = threading.Thread(target=test)
# t.start()
# e2 = time.time()
# print('耗时:', e2-e)
t = MyThread()
t.start()
e = time.time()
print('耗时:', e-s)
四、主线程和子线程
当一个程序启动时,一个单独的线程运行,就是主线程.新创建的线程,称为子线程.
python主线程和子线程的结束顺序
?主线程退出后子线程的运行状态依赖于它所在的进程,如果进程没有退出的话子线程依然正常运行.如果进程退出了,那么所有的线程都会退出,所以子线程也会退出.
?主线程退出,进程会等待所有子线程执行完毕后才结束
进程启动后会默认产生一个主线程,默认情况下主线程创建的子线程都不是守护线程(setDaemon(False)).因此主线程结束后,子线程会继续执行,进程会等待所有子线程执行完毕后才结束.
?主线程结束后进程不等待守护线程完毕,立即结束 当设置一个线程为守护线程时,此线程所属进程不会等待此线程运行结束,进程会立即结束.
t是守护线程,t2不是守护线程.因此,进程会等待t2执行完毕,而不会等待t完毕就会结束进程.
import time, threading
def test1():
for i in range(10):
time.sleep(1)
print('test1----')
# def test2():
# for i in range(5):
# time.sleep(1)
# print('test2----')
if __name__ == '__main__':
print('主线程开始运行')
t = threading.Thread(target=test1)
# t2 = threading.Thread(target=test2)
t.setDaemon(True) # 设置为守护线程
t.start()
# t2.start()
print('主线程结束')
主线程等待子线程完成后结束
在线程中使用join进行阻塞,会等待调用join的线程执行完毕后才会执行后面的内容.
关于Python线程(一)的介绍今天就到这里啦,后续我会为大家介绍线程(二)的相关知识哦~
关注我,带你领略Python的风采~😍😍😍
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!