python threading父进程不死,子线程不退出..如何才能使用完线程后回收线程?

最近使用python的多线程 进行并发的ping操作,其中使用in_queue和out_queue两个阻塞队列,来确保线程安全.发现一个问题,

就是,创建多线程的主进程只要不退出,它(主进程)所创建的所有线程不会被杀死,只是状态均为sleeping状态而已,这样会有一个问题,就是linux系统分配给每个用户所开进程最大数目是有限制的,如果一个进程比如flask或者django在运行后,理论上不会退出的,这样会创建出越来越多的线程,早晚会达到上限,这样系统不能分配任何资源给这个用户了....

代码如下:

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from threading import Thread 
import subprocess 
from Queue import Queue, Empty
import re 
import sys,os,time 
import platform 

def ping(
    hostname = None,
    count = 1,
    timeout = 3
):
    data = {
        ‘errorcode‘:0xff,
        ‘errorinfo‘:None,
        ‘data‘:{
            ‘hostname‘:hostname,
            ‘isUp‘:None
        }
    }
    try:
        outfile = ‘‘
        if "Linux" == platform.system():
            cmd = "ping -c %d -w %d %s"%(count,timeout,hostname)
            outfile = "/dev/null"
        elif "Windows" == platform.system():
            cmd = "ping -n %d -w %d %s"%(count,timeout,hostname)
            outfile = "ping.temp"
        ret = subprocess.call(cmd, shell=True, stdout=open(outfile,‘w‘), stderr=subprocess.STDOUT)
        data[‘data‘][‘isUp‘] = True if 0 == ret else False
        data[‘errorcode‘] = 0x00
    except Exception,e:
        print traceback.format_exc()
    finally:
        return data
        
        
        
def ping_with_queue(in_queue, out_queue):
    while True:
        ip = in_queue.get()
        data = ping(hostname = ip)
        out_queue.put(data)
        in_queue.task_done()#向任务已完成的队列,发送一个通知信号

def append_result(out_queue, result):
    while True:
        data = out_queue.get()
        result.append(data)
        out_queue.task_done()#向任务已完成的队列,发送一个通知信号

        
        
def get_all_device_status(ips):
    data = {
        ‘errorcode‘:0xff,
        ‘errorinfo‘:None,
        ‘data‘:[]
    }
    result = []
    threads_nums = len(ips)
    in_queue = Queue()
    out_queue = Queue()
    for i in range(threads_nums):
        t = Thread(target=ping_with_queue, args=(in_queue,out_queue))
        t.setDaemon(True)
        t.start()
        
    for ip in ips:
        in_queue.put(ip)

    for i in range(threads_nums):
        t = Thread(target=append_result, args=(out_queue,data[‘data‘]))
        t.setDaemon(True)
        t.start()
    data[‘errorcode‘] = 0x00
    in_queue.join()
    out_queue.join()
    return data

if __name__ == ‘__main__‘:
    ips = [ ‘10.1.31.‘+str(i) for i in xrange(0xff)]
    print get_all_device_status(ips)
    print ‘main process begin sleep 20 seconds....‘
    time.sleep(20)
    print ‘main process exit‘

运行过程图文解释如下:

  1. 程序未运行,系统的线程状态如下,top -H显示如下:系统当前共有592个线程,其中1个处于运行状态,其他的处于sleep状态
  2. 运行系统,但是多线程任务还没有执行完毕,in_queue和out_queue队列还是阻塞状态,top -H 显示如下: 这时系统中共有1480个现场,也就是说我的程序创建1480-592 +1= 889个线程,理论上会创建255*2= 510个线程,至于多创建多出来的889-510 = 379个线程,我猜是subprocescess 调用系统的ping命令先关,再次不考虑这379个线程的情况,只考虑510个线程的去向...但是这个不是重点,这个阶段,两个队列还时处于阻塞状态,创建的多线程还未全部返回
  3. in_queue和out_queue两个队列不在阻塞主进程,多线程任务执行完成,get_all_device_status(ips)已经有了返回值,主进程沉睡20秒,shell显示如下:主进程因为time.sleep(20)进入20秒的睡眠中,这时top -H 显示如下:in_queue和out_queue已经不再阻塞主进程了,任务也有了返回值,但是显示共有1101个线程,也就是还剩余1101-592+1 = 510 也就是subprocess那30多哥线程已经退出了,但是程序创建的510个线程一个都没有退出...
  4. 主进程沉睡20秒,退出,程序运行完毕,住进成退出,它所创建的所有线程均已退出,当前系统中线程的数目为:590,也就是1101-590+1 = 512个线程,在主进程退出后才退出...top -H显示如下:这就是问题,如果主进程沉睡的时间更长,比如一年,那么再一年内,所有的线程都不会退出,更早的是,如果重复运行该程序,每次创建的510个线程,均不能退出....这样早晚会把操作系统分配给当前用户的最大线程数目用完(ulimit -n)...到时候,该用户所有操作,均不能使用....
  5. 总结,按照我现在的代码,就是线程执行任务完后,还是会存在,状态编程sleeping状态,只有主进程退出才能退出....但是如果用flask或者django调用多线程的时候,由于flask和django等轻易不会退出...所以就会出现我说的那个问题...所以说,怎么才能使用threading queue 任务有返回之后,主进程杀死所创建的线程.....?
时间: 2024-12-07 15:33:36

python threading父进程不死,子线程不退出..如何才能使用完线程后回收线程?的相关文章

线程暴长~Quartz中创建Redis频繁后导致线程暴长

在最近项目开发过程中,在进行任务调度处理过程中,出现了一个问题,它的线程数暴长,从20多个可以到1000多个,如果你的服务器性能好的话,可以到10000多个,太恐怖了,就算你的服务再好,早晚有一天也会被new Redis炸干!哈哈! 解决方法: 使用单例模式减少new redis的次数 对于我们应用程序的线程,如果它持续增长,那么,你就要看一下那么非托管资源是否被释放了,这个要重视起来.

python并发编程-进程理论-进程方法-守护进程-互斥锁-01

操作系统发展史(主要的几个阶段) 初始系统 1946年第一台计算机诞生,采用手工操作的方式(用穿孔卡片操作) 同一个房间同一时刻只能运行一个程序,效率极低(操作一两个小时,CPU一两秒可能就运算完了) 联机批处理系统 脱机批处理系统 多道程序系统 1.空间上的复用 ? 多个程序公用一套计算机硬件 2.时间上的复用 ? 切换+保存状态 ? 保存状态:保存当前的运行状态,下次接着该状态继续执行 ? 切换的两种情况 ? (1) 当一个程序遇到 I/O 操作(不需要使用CPU),操作系统会剥夺该程序的C

python中的进程、线程(threading、multiprocessing、Queue、subprocess)

Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等. 每次执行程序的时候,都会完成一定的功能,比如说浏览器帮我们打开网页,为了保证其独立性,就需要一个专

python学习笔记-进程线程

1.什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本:进程是程序的一次执行活动,属于动态概念. 在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行.这是这样的设计,大大提高了CPU的利用率.进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的. 2.什么是线程(thread

转载--Python之路,进程、线程、协程篇(原文地址:http://www.cnblogs.com/alex3714/articles/5230609.html)

本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queue队列 开发一个线程池 进程 语法 进程间通讯 进程池 进程与线程 什么是线程(thread)? 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 A

python学习之-- 进程 和 线程

python 进程/线程详解 进程定义:以一个整体的形式暴露给操作系统管理,它里面包含对各种资源的调用,内存的管理,网络接口的调用等等,对各种资源管理的集合,就可以叫做一个进程. 线程定义:线程是操作系统能够进行运算调度的最小单位(是一串指令的集合).它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 另说明:进程是不能直接操作CPU执行的,每个进程的执行都是默认创建一个主线程来操作CPU进行执行指令集合

python学习之进程线程学习一

一.概念 进程: 未完成任务而执行一堆代码的过程,进程是任务,真正执行进程的是cpu 并行: 多个cpu同时运行 并发: 单个cpu分时操作,利用单cpu 的多道技术,看起来像是程序同时运行,其实是分时段运行, 只不过cpu切换速度比较快,并行也属于并发. 多道技术:内存中同时存入多道(多个)程序,cpu从一个进程快速切换到另外一个,使每个进程各 自运行几十或几百毫秒,这样,虽然在某一个瞬间,一个cpu只能执行一个任务,但在1秒内,cpu却 可以运行多个进程,这就给人产生了并行的错觉,即伪并发,

Python并发编程-进程 线程 协程

一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据集:数据集则是程序在执行过程中所需要使用的资源 3.进程控制块:进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感 知进程存在的唯一标志. 二.线程                                                                        

自动化运维Python系列之进程、线程、协程

进程 线程 协程 1)进程是具有一定独立功能的的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的独立单位 2)线程是进程的一个实体,是CPU调度和分派的基本单位 3)协程是程序自身产生的一种线程复用机制,作用是让一个线程重复利用,减少系统资源开销,提高程序效率 由于进程.线程都是操作系统的基本概念,比较抽象,我们可以将CPU看作是一个时刻在运行中的大型工厂,车间就是工厂里具有独立工作能力的程序进程,每个车间里工作的机器人就是线程: 系统工作模式: 同一时间工厂只能为一个车间供电,