【Python】获取网页标题的工具第三版

什么是线程池?##

诸如web服务器、数据库服务器、文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务。构建服务器应用程序的一个过于简单的模型是:每当一个请求到达就创建一个新的服务对象,然后在新的服务对象中为请求服务。但当有大量请求并发访问时,服务器不断的创建和销毁对象的开销很大。所以提高服务器效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这样就引入了“池”的概念,“池”的概念使得人们可以定制一定量的资源,然后对这些资源进行复用,而不是频繁的创建和销毁。

线程池是预先创建线程的一种技术。线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中。这些线程都是处于睡眠状态,即均为启动,不消耗CPU,而只是占用较小的内存空间。当请求到来之后,缓冲池给这次请求分配一个空闲线程,把请求传入此线程中运行,进行处理。当预先创建的线程都处于运行状态,即预制线程不够,线程池可以自由创建一定数量的新线程,用于处理更多的请求。当系统比较闲的时候,也可以通过移除一部分一直处于停用状态的线程。

线程池的注意事项

虽然线程池是构建多线程应用程序的强大机制,但使用它并不是没有风险的。在使用线程池时需注意线程池大小与性能的关系,注意并发风险、死锁、资源不足和线程泄漏等问题。

(1)线程池大小。多线程应用并非线程越多越好,需要根据系统运行的软硬件环境以及应用本身的特点决定线程池的大小。一般来说,如果代码结构合理的话,线程数目与CPU 数量相适合即可。如果线程运行时可能出现阻塞现象,可相应增加池的大小;如有必要可采用自适应算法来动态调整线程池的大小,以提高CPU 的有效利用率和系统的整体性能。

(2)并发错误。多线程应用要特别注意并发错误,要从逻辑上保证程序的正确性,注意避免死锁现象的发生。

(3)线程泄漏。这是线程池应用中一个严重的问题,当任务执行完毕而线程没能返回池中就会发生线程泄漏现象。

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

from threading import Thread
from Queue import Queue
from bs4 import BeautifulSoup
import signal
import sys
import urllib2
import ssl
if hasattr(ssl, '_create_unverified_context'):
    ssl._create_default_https_context = ssl._create_unverified_context


def get_title(ip):
    try:
        ip = ip.strip("\r\n")
        print ip
        req = urllib2.Request("http://" + ip)
        resp = urllib2.urlopen(req, data=None, timeout=3)
        respHtml = resp.read()
        soup = BeautifulSoup(respHtml, 'lxml')
        tables = soup.findAll('title')
        print tables
        ret = open("ret.txt", "a")  # save ret
        ret.write(ip + "        " + str(tables) + "\n")
        ret.close()
    except Exception as e:
        ret = open("ret.txt", "a")  # save ret
        ret.write(ip + "        " + str(e) + "\n")
        ret.close()
        print e


class Worker(Thread):
    def __init__(self, taskQueue):
        Thread.__init__(self)
        self.setDaemon(True)
        self.taskQueue = taskQueue
        self.start()

    def run(self):
        while 1:
            try:
                callable, args, kwds = self.taskQueue.get(block=False)
                self.taskQueue.get(block=False)
                print callable(*args, **kwds)
            except:
                break


class ThreadPool:
    def __init__(self):
        self.threads = []
        self.taskQueue = Queue()
        self.threadNum = num_thread
        self.__create_taskqueue()
        self.__create_threadpool(self.threadNum)

    def __create_taskqueue(self):
        f = open("d:\\port.txt", 'r') #要扫描的IP文件
        lines = f.readlines()
        for ip in lines:
            self.add_task(get_title, ip)

    def __create_threadpool(self, threadNum):
        for i in range(threadNum):
            thread = Worker(self.taskQueue)
            self.threads.append(thread)

    def add_task(self, callable, *args, **kwds):
        self.taskQueue.put((callable, args, kwds))

    def new_complete(self):
        for item in self.threads:
            if item.isAlive(): item.join()


def handler(signum, frame):
    global is_exit
    print "CTRL+C Is Pressed"
    sys.exit(0)


if __name__ == '__main__':
    num_thread = 20 #设置线程数
    signal.signal(signal.SIGINT, handler)
    signal.signal(signal.SIGTERM, handler)

    tp = ThreadPool()
    tp.new_complete()


参考:
http://blog.csdn.net/hzrandd/article/details/10074163

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,337评论 19 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,216评论 25 709
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,441评论 11 349
  • 前一阵的在思考为什么张小龙能够做出来微信。 我觉得,除了腾讯内部的架构问题,还有他个人的产品经理的直觉,或者可以说...
    青空片想阅读 3,345评论 0 1
  • 二、怀念奶奶 我的奶奶是2011年7月28日去世的。 那天晚上12点多,我们都进入了梦乡,突然客厅的电话响了起来,...
    西川紫阅读 3,097评论 0 0