线程池概念

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

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

线程池的注意事项
虽然线程池是构建多线程应用程序的强大机制,但使用它并不是没有风险的。在使用线程池时需注意线程池大小与性能的关系,注意并发风险、死锁、资源不足和线程泄漏等问题。
1、线程池大小。多线程应用并非线程越多越好,需要根据系统运行的软硬件环境以及应用本身的特点决定线程池的大小。

一般来说,如果代码结构合理的话,线程数目与CPU 数量相适合即可。
如果线程运行时可能出现阻塞现象,可相应增加池的大小;如有必要可采用自适应算法来动态调整线程池的大小,以提高CPU 的有效利用率和系统的整体性能。
2、并发错误。多线程应用要特别注意并发错误,要从逻辑上保证程序的正确性,注意避免死锁现象的发生。
3、线程泄漏。这是线程池应用中一个严重的问题,当任务执行完毕而线程没能返回池中就会发生线程泄漏现象。

线程池要点

线程池要点:

Python之路【第八篇】python实现线程池
线程池要点:
1、通过判断等待的任务数量和线程池中的最大值,取最小值来判断开启多少线程来工作
比如:
任务数是3,进程池最大20  ,那么咱们只需要开启3个线程就行了。
任务数是500,进程池是20,那么咱们只开20个线程就可以了。
取最小值

2、实现线程池正在运行,有一个查看的功能,查看一下现在线程里面活跃的线程是多少等待的是多少?

线程总共是多少,等待中多少,正在运行中多少
作用:
方便查看当前线程池状态
能获取到这个之后就可以当线程一直处于空闲状态

查看状态用:上下文管理来做,非常nice的一点

3、关闭线程
Python之路【第八篇】python实现线程池

简单线程池实现

#!/usr/bin/env python
#-*- coding:utf-8 -*-
__author__ = 'luo_t'
import Queue
import threading
import time

'''
这个简单的例子的想法是通过:
1、利用Queue特性,在Queue里创建多个线程对象
2、那我执行代码的时候,去queue里去拿线程!
如果线程池里有可用的,直接拿。
如果线程池里没有可用,那就等。
3、线程执行完毕,归还给线程池
'''

class ThreadPool(object): #创建线程池类
    def __init__(self,max_thread=20):#构造方法,设置最大的线程数为20
        self.queue = Queue.Queue(max_thread) #创建一个队列
        for i in xrange(max_thread):#循环把线程对象加入到队列中
            self.queue.put(threading.Thread)
            #把线程的类名放进去,执行完这个Queue

    def get_thread(self):#定义方法从队列里获取线程
        return self.queue.get()

    def add_thread(self):#定义方法在队列里添加线程
        self.queue.put(threading.Thread)

pool = ThreadPool(10)

def func(arg,p):
    print arg
    time.sleep(2)
    p.add_thread() #当前线程执行完了,我在队列里加一个线程!

for i in xrange(300):
    thread = pool.get_thread() #线程池10个线程,每一次循环拿走一个!默认queue.get(),如果队列里没有数据就会等待。
    t = thread(target=func,args=(i,pool))
    t.start()


'''
self.queue.put(threading.Thread) 添加的是类不是对象,在内存中如果相同的类只占一份内存空间
并且如果这里存储的是对象的话每次都的新增都得在内存中开辟一段内存空间

还有如果是对象的话:下面的这个语句就不能这么调用了!
for i in xrange(300):
    thread = pool.get_thread()
    t = thread(target=func,args=(i,pool))
    t.start()
    通过查看源码可以知道,在thread的构造函数中:self.__args = args  self.__target = target  都是私有字段那么调用就应该这么写

for i in xrange(300):
    ret = pool.get_thread()
    ret._Thread__target = func
    ret._Thread__args = (i,pool)
    ret.start()
'''
simple_pool.py

复杂线程池需要知道的知识点

#!/usr/bin/env python
#-*- coding:utf-8 -*-
__author__ = 'luo_t'

import Queue
obj = object() #object也是一个类,我创建了一个对象obj

q = Queue.Queue()
for i in range(10):
    print id(obj)#看萝卜号
    q.put(obj)
'''
这个队列里有10个萝卜(萝卜=obj),但是这10个萝卜只是个投影。
我们在for循环的时候put到队列里,obj有变化吗?是否有新开辟空间?显然没有
'''
knowledge_point_1.py

相关文章:

  • 2021-09-08
  • 2021-12-08
  • 2021-06-10
  • 2021-07-22
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-07-20
  • 2021-11-21
  • 2021-07-30
  • 2022-12-23
相关资源
相似解决方案