1、学习目标
线程池使用
2、编程思路
2.1 代码原理
线程池是预先创建线程的一种技术。线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中。这些线程都是处于睡眠状态,即均为启动,不消耗 CPU,而只是占用较小的内存空间。当请求到来之后,缓冲池给这次请求分配一个空闲线程,把请求传入此线程中运行,进行处理。当预先创建的线程都处于运行 状态,即预制线程不够,线程池可以自由创建一定数量的新线程,用于处理更多的请求。当系统比较闲的时候,也可以通过移除一部分一直处于停用状态的线程。
一个典型的线程池,应该包括如下几个部分:
1、线程池管理器(ThreadPool),用于启动、停用,管理线程池
2、工作线程(WorkThread),线程池中的线程
3、请求接口(WorkRequest),创建请求对象,以供工作线程调度任务的执行
4、请求队列(RequestQueue),用于存放和提取请求
5、结果队列(ResultQueue),用于存储请求执行后返回的结果
2.2 编写细节
- 1、定制线程数
ThreadPool(poolsize)
例如定制20个线程数:
ThreadPool(20)
- 2、创建要开启多线程的函数
makeRequests(some_callable, list_of_args, callback)
some_callable:开启多线程的函数
list_of_args:函数相关参数
callback:回调函数
- 3、运行多线程的请求扔进线程池
第三步将多线程请求丢进线程池,官方说明是一行代码:
[pool.putRequest(req) for req in requests]
这行代码如果用简单容易理解的编写方式去写那就相当于:
for req in requests:
pool.putRequest(req)
然后丢进线程池后,还有一个退出的函数。
pool.wait()
例子:
>>> pool = ThreadPool(poolsize) # 定制线程数
>>> requests = makeRequests(some_callable, list_of_args, callback) # 创建要开启多线程的函数
>>> [pool.putRequest(req) for req in requests] # 将多线程的请求扔进线程池
>>> pool.wait() # 等待所有的线程完成工作后退出
3 实现代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import json
import threading
import requests
import urllib2
import sys
import threading
from time import ctime,sleep
import threadpool
# 主要执行函数
def main():
f = open("target.txt")
line = f.readlines()
global g_list
g_list = []
urllist = []
for url in line:
url = url.rstrip() # 读取文本
urllist.append(url) # 保存url的列表
thread_requestor(urllist) # 线程池函数
f = open('vulurl.txt','w')
for q in g_list: # 保存线程回调函数的值到vulurl.txt中
f.write(q+"
")
f.close()
# 回调函数的结果保存到g_list数组中
def res_printer(res1,res2):
if res2:
#print ('"线程返回的地址 = " %s ')% res2
g_list.append(res2)
else:
pass
# 线程池函数
def thread_requestor(urllist):
pool = threadpool.ThreadPool(200) # 线程池数量
reqs = threadpool.makeRequests(getScan,urllist,res_printer) # 使用线程池
[pool.putRequest(req) for req in reqs] # 简写 for req in reqs pool.putRequest(req)
pool.wait()
# 检测HTTP状态码函数
def getScan(url):
try:
requests.packages.urllib3.disable_warnings() # 忽略HTTPS连接错误的警告
status = requests.get(url, proxies=None, timeout=3,verify=False) # 获取HTTP状态码
print "scanning " + url + "
" # 正在扫描的地址
if status.status_code == 200: # 访问成功的网站可以返回
return url
else:
pass
except:
pass
if __name__ == "__main__":
main()
4、参考文章
python(13)多线程:线程池,threading
http://www.cnblogs.com/lovychen/p/5411743.html
Threadpool
https://chrisarndt.de/projects/threadpool/