python主线程有两个子线程、创建两个主函数_python 中关于多线程的两个问题

我也刚看,试了好久,初步知道怎么回事了.

先回答你的两个问题:

1、setDaemon所绑定的都是主线程,都是一样的,即运行py文件第一次创建的那个线程(也是主进程),有且只有一个

2、queue.join()如果单独使用会被无限挂起,字面翻译为等待队列为空,再执行别的操作.但是他等待的队列不是我们创建的aqueue,而是一个与aqueue长度相等的一个"需要完成的子线程"队列,他判断的很可能是这个列表,当这个列表为空时queue.join()才成立,所以如楼上的那位所说queue.join()要结合aqueue.task_done()函数来使用,aqueue.task_done()的意思是每task_done一次 就从"需要完成的子线程"队列里删掉一个元素,这样在最后join的时候根据队列长度是否为零来判断队列是否结束,aqueue.task_done()用在子线程函数中,这样queue.join()才知道完成了多少个子线程,才不会无限挂起,也就是为什么你没退出的原因

但是你的程序也有问题:

主要的问题是,守护线程机制:主线程运行完毕去结束子线程时,由于有大量的子线程还在time.sleep(5),结束这些子线程会触发异常:

Fatal Python error: could not acquire lock for <_io.bufferedwriter name="<stdout>"> at interpreter shutdown, possibly due to daemon threads

Thread 0x000019cc (most recent call first):

File "test.py", line 13 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

这是因为:

下面的一些说法是错误的,可以看我后面的补充,这里就不改了,是一种猜测,但是应该确实不是这样

喂不饱的子线程:你aqueue.put(i)了是10个元素,但是却运行了20个子线程来"吃"这10个元素,又因为这20个线程都是守护进程,当10个吃饱了,这个10个卡在了item = aqueue.get()等待接受元素,另外的那些很有可能卡在了time.sleep(5)上,而主线程运行完毕,准备结束所有的守护进程,我判断,结束卡在item = aqueue.get()的守护进程不会报错,而结束其他程序,如time.sleep会触发异常,这也是为啥楼上那位吧你的for i in range(20):改成了for i in range(1):的原因.

还有两种退出的方式:

1、是在子线程里判断队列是否为空:

if aqueue.empty() == True:

break

为空就退出

2、主线程通过queue向子线程发送退出命令

其实这里一般用pipe管道的,Queue队列不好针对特定的线程进行退出操作,大概的伪码为:

主线程:

aqueue.put('quit')

子线程""

item = aqueue.get()

if item == 'quit':

return

else:

# "do something"

所以多进程,多线程还是要控制好程序逻辑,控制好调度.

我没用过守护进程,我一般用的是普通的用户进程,这样主线程跑完会等待所有子线程运行完毕再结束

其实还没完=_=:

后面的都是我的猜测,算是附加的,选修:

这程序的细节也值得我们关注:

这程序如果真去实践的话很容易炸,以下都是我的猜测

如上所述,我们修改程序,注意注释

import queue

import threading

import time

aqueue = queue.Queue()

# 发送了0到9的十个数据

for i in range(10):

aqueue.put(i)

def worker():

while True:

# 输出当前线程,和主线程(可以看到主线程都一样)

print('thread %s is running...\nmain_thread %s is running...\n\n' % (threading.current_thread().name,threading.main_thread()))

time.sleep(1)

item = aqueue.get()

print(item)

aqueue.task_done()

print('thread end')

n = 1

"""注意这!!!!!!!!!!!!!!!!!!"""

# 运行了10个线程来处理这十个数据

for i in range(10):

print("run thread Counts: ",n)

n += 1

a = threading.Thread(target = worker)

a.setDaemon(True)

a.start()

aqueue.join()

print('after to do')

print('end')

10个数据10个线程,time.cleep(5)秒结果会怎么样?运行正常?

很不幸运的炸了23333333

有一定的几率报错,和上面一样:

Fatal Python error: could not acquire lock for <_io.bufferedwriter name="<stdout>"> at interpreter shutdown, possibly due to daemon threads

Thread 0x0000063c (most recent call first):

File "test.py", line 13 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

我电脑上大部分运行正常,只有几次会这样,为什么会这样?

换成10个数据9个线程就不会出错了

我猜测的情况是,初步认为:

直接看完整的输出,注意看有注释的地方:

run thread Counts: 1

thread Thread-1 is running...

main_thread <_mainthread started> is running...

run thread Counts: 2

thread Thread-2 is running...

main_thread <_mainthread started> is running...

run thread Counts: 3

thread Thread-3 is running...

main_thread <_mainthread started> is running...

run thread Counts: 4

thread Thread-4 is running...

main_thread <_mainthread started> is running...

run thread Counts: 5

thread Thread-5 is running...

main_thread <_mainthread started> is running...

run thread Counts: 6

thread Thread-6 is running...

main_thread <_mainthread started> is running...

run thread Counts: 7

thread Thread-7 is running...

main_thread <_mainthread started> is running...

run thread Counts: 8

thread Thread-8 is running...

main_thread <_mainthread started> is running...

run thread Counts: 9

thread Thread-9 is running...

main_thread <_mainthread started> is running...

run thread Counts: 10

thread Thread-10 is running...

main_thread <_mainthread started> is running...

0

1

3

4

thread end

thread end

5

2

thread Thread-2 is running...

main_thread <_mainthread started> is running...

thread end

thread end

thread end

thread Thread-3 is running...

main_thread <_mainthread started> is running...

thread end

thread Thread-4 is running...

main_thread <_mainthread started> is running...

thread Thread-1 is running...

main_thread <_mainthread started> is running...

thread Thread-5 is running...

main_thread <_mainthread started> is running...

6

8

thread Thread-6 is running...

main_thread <_mainthread started> is running...

thread end

thread end

thread Thread-7 is running...

main_thread <_mainthread started> is running...

7

9

thread Thread-9 is running...

main_thread <_mainthread started> is running...

"""到这里主线程已经完毕"""

thread end

after to do

"""

这里其实系统在调用守护线程的结束程序来结束所有子线程

"""

"""但是在结束守护进程程序后,又运行了一个不该运行的子线程,这就是为什么会报错的原因"""

thread Thread-10 is running...

main_thread <_mainthread started> is running...

end

thread end

thread Thread-8 is running...

main_thread <_mainthread started> is running...

Fatal Python error: could not acquire lock for <_io.bufferedwriter name="<stdout>"> at interpreter shutdown, possibly due to daemon threads

Thread 0x00000424 (most recent call first):

File "test.py", line 14 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Thread 0x00000f04 (most recent call first):

File "test.py", line 14 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Thread 0x0000165c (most recent call first):

File "test.py", line 13 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Thread 0x000018b0 (most recent call first):

File "test.py", line 14 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Thread 0x00000db4 (most recent call first):

File "test.py", line 14 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Thread 0x00001a88 (most recent call first):

File "test.py", line 14 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Thread 0x0000111c (most recent call first):

File "test.py", line 14 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Thread 0x0000177c (most recent call first):

File "test.py", line 14 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Thread 0x000008e4 (most recent call first):

File "test.py", line 14 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Thread 0x00001788 (most recent call first):

File "test.py", line 14 in worker

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 864 in run

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 916 in _bootstrap_inner

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\threading.py", line 884 in _bootstrap

Current thread 0x00001a18 (most recent call first):

看主要的几句

"""到这里主线程已经完毕"""

thread end

after to do

"""

这里其实系统在调用守护线程的结束程序来结束所有子线程

"""

"""但是在结束守护进程程序后,又运行了一个不该运行的子线程,这就是为什么会报错的原因"""

thread Thread-10 is running...

main_thread <_mainthread started> is running...

end

thread end

先这样吧,可以自己运行下程序看看

看了另一个答主的,使用了a.join()也是一种选择

改成发送10个数据,用9个线程跑,效率是最高的(理论)

import queue

import threading

import time

aqueue = queue.Queue()

# 发送了0到9的十个数据

for i in range(10):

aqueue.put(i)

def worker():

while True:

# 输出当前线程,和主线程(可以看到主线程都一样)

print('thread %s is running...\nmain_thread %s is running...\n\n' % (threading.current_thread().name,threading.main_thread()))

time.sleep(5)

item = aqueue.get()

print(item)

aqueue.task_done()

print('thread end')

n = 1

"""注意这!!!!!!!!!!!!!!!!!!"""

for i in range(9):

print("run thread Counts: ",n)

n += 1

a = threading.Thread(target = worker)

a.setDaemon(True)

a.start()

aqueue.join()

print('after to do')

print('end')

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值