1,进程是为线程执行而准备的所有资源,线程是操作系统可以调用的最小执行时间单元。即进程是所有资源,线程是执行命令,一个进程至少有一个主线程
t = threading.Thread(target=run1,args=("t1",)) args是一个元组形式,如果只有一个参数,后面也得跟一个逗号
t.join() 等待当前线程执行完才继续向下执行
t.setDaemon(True) 设置当前线程为守护线程,即在主线程结束完成后,最后退出时不用等待守护线程,有一个用处是,主线程退出了,其守护线程也死了
threading.current_thread()查看当前线程
threading.active_count()查看当前活动线程个数,可以利用线程个数为1来判断所有子线程是不是执行完成了
互斥锁及用户态锁 递归锁
2, queue 队列
queue.Queue(maxsize=3) 设置队列最大长度,不设置无限大。先进先出
queue.LifoQueue() 后进先出
queue.PriorityQueue() 按优先级出
queue.empty() 队列是否为空
queue.full() 是否为满了
queue.qsize() 打印队列长度
Queue.put(item, block=True, timeout=None) 入队一个item,如果队列满了,会一直等待队列被取走一个,不然一直卡着,除非block=False。或者卡timeout秒,都会报异常
Queue.get(block=True, timeout=None) 出队一个item,如果队列是空的也会一直卡着,直到有入队,block,timeout同上
Queue.put_nowait() Queue.get_nowait() 不卡入出队,满空会报错
在网上大多关于join()与task_done()的结束原话是这样的:
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号Queue.join() 实际上意味着等到队列为空,再执行别的操作
但是可能很多人还是不太理解,这里以我自己的理解来阐述这两者的关联。
理解
如果线程里每从队列里取一次,但没有执行task_done(),则join无法判断队列到底有没有结束,在最后执行个join()是等不到结果的,会一直挂起。
可以理解为,每task_done一次 就从队列里删掉一个元素,这样在最后join的时候根据队列长度是否为零来判断队列是否结束,从而执行主线程。
下面看个自己写的例子:
下面这个例子,会在join()的地方无限挂起,因为join在等队列清空,但是由于没有task_done,它认为队列还没有清空,还在一直等。
注意点:
put队列完成的时候千万不能用task_done(),否则会报错:
task_done() called too many times
因为该方法仅仅表示get成功后,执行的一个标记。所以只能这样用,put入队一个item,执行join(),卡主等待get出队并执行task_done(),之前的卡由于收到task done就继续运行了
#!_*_coding:utf-8_*_
#__author__:"Alex huang"
import queue,time,threading
a = queue.Queue(10)
def put(name):
while True:
# for i in range(5):
# a.put("包子{}".format(i+1))
a.put(1)
print("[%s]生产了5个包子" %name)
#time.sleep(5)
a.join()
def get(name):
while True:
print("[%s]吃了%s" %(name,a.get()))
time.sleep(1)
a.task_done()
# if a.qsize() == 0:
# a.task_done()
# print("chi wan le")
t1 = threading.Thread(target=put,args=("Alex",))
t1.start()
t11 = threading.Thread(target=put,args=("HHH",))
t11.start()
t2 = threading.Thread(target=get,args=("hong",))
t3 = threading.Thread(target=get,args=("keke",))
t3.start()
t2.start()
浙公网安备 33010602011771号