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+"\n")
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 + "\n" # 正在掃描的地址
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/