精华内容
下载资源
问答
  • 线程池pool
    千次阅读
    2021-09-07 15:34:46
    import requests
    import time
    from multiprocessing.dummy import Pool
    
    headers = {
        'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }
    
    urls = [
        'https://sp1.baidu.com/',
        'https://sp1.baidu.com/',
        'https://sp1.baidu.com/',
        'https://www.baidu.com/'
    ]
    
    
    def get_url(url):
        print('正在访问',url)
        res = requests.get(url=url,headers=headers)
        print('访问状态:',res.status_code)
        time.sleep(2)
    
    
    while True:
        pool = Pool(4)
        pool.map(get_url,urls)
    

    以上就是线程池pool.map的方法,比较简单。Pool(9)括号里面写多少就是多少个线程

    更多相关内容
  • 36 多线程之线程池pool

    2021-08-19 11:12:15
    将任务添加到线程池中,线程池会自动指定一个空闲的线程池的最大线程数时,任务需要等待有新的空闲线程后才会被执行。 我们可以使用threading模块及queue模块定制线程池,也可以使用multiproce

    在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或其他更多资源。虚拟机也将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。同样的道理,多任务情况下每次都会生成一个新线程,执行任务后资源再被回收就显得非常低效,因此线程池就是解决这个问题的办法。类似的还有连接池,进程池。

    将任务添加到线程池中,线程池会自动指定一个空闲的线程池的最大线程数时,任务需要等待有新的空闲线程后才会被执行。

    我们可以使用threading模块及queue模块定制线程池,也可以使用multiprocessing。 from multiprocessing import Pool 这样导入的Pool表示的是进程池,from multiprocessing.dummy import Pool 这样导入的Pool表示的是线程池

    【示例 1】线程池示例

     运行结果如下:

    上述代码模拟一个耗时2秒的任务,比较其顺序执行5次和线程池(并发数为5)执行的耗时。显然并发执行效率更高,接近单词执行的时间。

    总结:Python多线程适合用在I/O密集型任务中。I/O密集型任务较少时间用在CPU上,较多时间用在I/O上,如文件读写、web请求、数据库请求等;而对于计算密集型任务,应该使用多进程。

     

    展开全文
  • Python线程池(thread pool)创建及使用+实例代码

    千次阅读 多人点赞 2022-05-31 17:42:56
    我们先从线程到线程池,从每个线程的运行到多个线程并行,再到线程池管理。由浅入深的理解如何在实际开发中,使用线程池来提高处理线程的效率。 一、线程 线程(英语:thread)是操作系统能够进行运算调度的最小...


    前言

    首先线程和线程池不管在哪个语言里面,理论都是通用的。对于开发来说,解决高并发问题离不开对多个线程处理。我们先从线程到线程池,从每个线程的运行到多个线程并行,再到线程池管理。由浅入深的理解如何在实际开发中,使用线程池来提高处理线程的效率。


    目录

    前言

    一、线程

    1.线程介绍

    2.线程特性

    1)轻型实体

    2)独立调度和分派的基本单位

    3)可并发执行

    4)共享进程资源

    二、线程池

    HS/HA半同步/半异步模式:

    L/F领导者与跟随者模式

    三、线程池的设计思路

    四、Python线程池构建

    1.构建思路

    2.实现库功能函数

     ThreadPoolExecutor()

    submit()

    result()

     cancel()

     cancelled()

     running()

    as_completed()

     map()

    点关注,防走丢,如有纰漏之处,请留言指教,非常感谢


    一、线程

    1.线程介绍

            线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及Sun中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

            60年代,在OS中能拥有资源和独立运行的基本单位是进程,然而随着计算机技术的发展,进程出现了很多弊端,一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程;二是由于对称多处理机(SMP)出现,可以满足多个运行单位,而多个进程并行开销过大。因此在80年代,出现了能独立运行的基本单位——线程(Threads)。

            线程是独立调度和分派的基本单位。线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 10的线程,进行混合调度。

            同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。

            一个进程可以有很多线程,每条线程并行执行不同的任务。        

    2.线程特性

    1)轻型实体

    线程中的实体基本上不拥有系统资源,只是有一点必不可少的、能保证独立运行的资源。

    线程的实体包括程序、数据和TCB。线程是动态概念,它的动态特性由线程控制块TCB(Thread Control Block)描述。TCB包括以下信息:

    (1)线程状态。

    (2)当线程不运行时,被保存的现场资源。

    (3)一组执行堆栈。

    (4)存放每个线程的局部变量主存区。

    (5)访问同一个进程中的主存和其它资源。

    用于指示被执行指令序列的、保留局部变量、少数状态参数返回地址等的一组寄存器堆栈

    2)独立调度和分派的基本单位

            在多线程OS中,线程是能独立运行的基本单位,因而也是独立调度和分派的基本单位。由于线程很“轻”,故线程的切换非常迅速且开销小(在同一进程中的)。

    3)可并发执行

            在一个进程中的多个线程之间,可以并发执行,甚至允许在一个进程中所有线程都能并发执行;同样,不同进程中的线程也能并发执行,充分利用和发挥了处理机与外围设备并行工作的能力。

    4)共享进程资源

            在同一进程中的各个线程,都可以共享该进程所拥有的资源,这首先表现在:所有线程都具有相同的地址空间(进程的地址空间),这意味着,线程可以访问该地址空间的每一个虚地址;此外,还可以访问进程所拥有的已打开文件、定时器等。由于同一个进程内的线程共享内存和文件,所以线程之间互相通信不必调用内核。

    二、线程池

            线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。 例如,线程数一般取cpu数量+2比较合适,线程数过多会导致额外的线程切换开销。

    任务调度以执行线程的常见方法是使用同步队列,称作任务队列。池中的线程等待队列中的任务,并把执行完的任务放入完成队列中。

    线程池模式一般分为两种:HS/HA半同步/半异步模式、L/F领导者与跟随者模式。

    HS/HA半同步/半异步模式:

            半同步/半异步模式又称为生产者消费者模式,是比较常见的实现方式,比较简单。分为同步层、队列层、异步层三层。同步层的主线程处理工作任务并存入工作队列,工作线程从工作队列取出任务进行处理,如果工作队列为空,则取不到任务的工作线程进入挂起状态。由于线程间有数据通信,因此不适于大数据量交换的场合。

    L/F领导者与跟随者模式

            领导者跟随者模式,在线程池中的线程可处在3种状态之一:领导者leader、追随者follower或工作者processor。任何时刻线程池只有一个领导者线程。事件到达时,领导者线程负责消息分离,并从处于追随者线程中选出一个来当继任领导者,然后将自身设置为工作者状态去处置该事件。处理完毕后工作者线程将自身的状态置为追随者。这一模式实现复杂,但避免了线程间交换任务数据,提高了CPU cache相似性。在ACE(Adaptive Communication Environment)中,提供了领导者跟随者模式实现。

    线程池的伸缩性对性能有较大的影响。

    • 创建太多线程,将会浪费一定的资源,有些线程未被充分使用。

    • 销毁太多线程,将导致之后浪费时间再次创建它们。

    • 创建线程太慢,将会导致长时间的等待,性能变差。

    • 销毁线程太慢,导致其它线程资源饥饿。

            在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些""池化资源""技术产生的原因。比如大家所熟悉的数据库连接池正是遵循这一思想而产生的,本文将介绍的线程池技术同样符合这一思想。

    以上介绍来源于百度百科: 线程  线程池

    三、线程池的设计思路

    首先我们根据上述已经了解了线程和线程池创建目的以及作用。让我们自己思考一下,如果是自己的业务上要用到大量的请求或者是查询处理,而我们只能的机器并不能一下就接受这么多的task涌入计算,这将消耗我们计算机大量资源。这时我们就该创建线程池来对线程进行管理,我们可以给线程预留一定的空间,让请求逐个进入线程处理,当请求超过我们给的线程数量时,等一个线程跑完了再跑下一个,这样就不会造成资源的浪费和达到资源重复利用。

    那么我们建立线程池的思路就有一下几点:

    • 控制线程,给予每个线程任务保证线程正常运行。
    • 限制线程数量,保证系统有足够的运行空间。
    • 资源复用,保证每个线程运行完成任务后能再度利用。
    • 控制运行时间,线程运行超过一定时间后停止任务转接下个任务,防止线程堵塞。

    有了这些思路,我们就可以充分利用Python自带的库来构建线程池了。

    四、Python线程池构建

    1.构建思路

    第一步,我们需要在线程池里面创建出很多个线程。第二步,当得到一个请求时候,就使用一个线程来运行·它。第三步,若多个任务则分配多个线程来运行。当其中一个线程运行完它的任务之后,将再次进行下一个任务使用。

    2.实现库功能函数

    首先python标准库里面是有threading库的,但是该库并没有线程池这个模块。要快速构建线程池,可以利用concurrent.futures,该库提供了ThreadPoolExecutor和ProcessPoolExecutor两个类,实现了对threading和multiprocessing的进一步抽象。这里我们只讨论ThreadPoolExecutor:

    from concurrent.futures import ThreadPoolExecutor

    这里我们可以看JAVA关于线程池的设计:

    构造方法:
    public ThreadPoolExecutor(int corePoolSize, //核心线程数量
                                  int maximumPoolSize,//     最大线程数
                                  long keepAliveTime, //       最大空闲时间
                                  TimeUnit unit,         //        时间单位
                                  BlockingQueue<Runnable> workQueue,   //   任务队列
                                  ThreadFactory threadFactory,    // 线程工厂
                                  RejectedExecutionHandler handler  //  饱和处理机制
    	) 
    { ... }
    

     参数和Python创建线程池是一样的,python创建线程池:

    #encoding:utf-8
    from concurrent.futures import ThreadPoolExecutor
    import threading
    #创建一个包含2条线程的线程池
    pool = ThreadPoolExecutor(max_workers = 2)  #定义两个线程

    这样就建立了一条简单的线程池,其中最大线程数为2 .

    def task(i):
        sleep_seconds = random.randint(1, 3)    #随机睡眠时间
        print('线程名称:%s,参数:%s,睡眠时间:%s' % (threading.current_thread().name, i, sleep_seconds))
        time.sleep(sleep_seconds)   #定义睡眠时间
    for i in range(10):#创建十个任务
        future1 = pool.submit(task, i)
    

     ThreadPoolExecutor()

    构造线程池实例,传入max_workers可以设置线程池中最多能同时运行的线程数目

    submit()

    提交线程需要执行的任务(函数名和参数)到线程池中,立刻返回一个future对象。

    result()

    取task的执行结果

     cancel()

    取消该 Future 代表的线程任务。如果该任务正在执行,不可取消,则该方法返回 False;否则,程序会取消该任务,并返回 True。

     调高点睡眠时间:

     cancelled()

    返回 Future 代表的线程任务是否被成功取消。

    for i in range(5):#创建十个线程
        future1 = pool.submit(task, i)
        print(future1.cancelled())

     

     running()

    for i in range(5):#创建十个线程
        future1 = pool.submit(task, i)
        print(future1.running())

    as_completed()

    as_completed()方法是一个生成器,在没有任务完成的时候,会阻塞,在有某个任务完成的时候,会yield这个任务,就能执行for循环下面的语句,然后继续阻塞住,循环到所有的任务结束。从结果也可以看出,先完成的任务会先通知主线程。

     map()

    除了submit,ThreadPoolExecutor还提供了map函数来添加线程,与常规的map类似,区别在于线程池的 map() 函数会为 iterables 的每个元素启动一个线程,以并发方式来执行 func 函数. 同时,使用map函数,还会自动获取返回值。

    #向线程池提交5个任务
    x = np.arange(5) 
    for i in pool.map(task,x):
          print('successful')


    点关注,防走丢,如有纰漏之处,请留言指教,非常感谢

    以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见。

    展开全文
  • 主要介绍了Java线程池ForkJoinPool实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 前言 项目中有一个逻辑是消费kafka消息,然后调用下游接口处理逻辑,作者在用kafka处理消息的时候,通过google的rateLimiter.acquire()方法来达到接口限流的目的,...在项目中的kafka消费端,有以下线程池的应用 @Au

    前言

    项目中有一个逻辑是消费kafka消息,然后调用下游接口处理逻辑,作者在用kafka处理消息的时候,通过google的rateLimiter.acquire()方法来达到接口限流的目的,但是发现,之后无论如何增大RateLimiter.create方法中的permitsPerSecond参数,接口QPS都没有变化,于是就有了下面的一系列猜测+验证的解决方法。

    猜测+验证

    首先可以从自己应用到的组件开始排查,然后定位到大概的地方,优化并验证。

    比如:
    在项目中的kafka消费端,有以下线程池的应用

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    
     // 异步执行
     try {
          taskExecutor.execute(() -> dosomething());
     } catch (Exception e) {
          log.error("execute# 处理dosomething方法发送线程池打满了", e);
      }
    

    于是查看线程池的配置:

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setKeepAliveSeconds(60);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(1000);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
    

    线程池的核心数为5,最大线程数为20,队列数量为1000,我猜想是不是有可能线程任务在排队导致处理不过来,从而导致接口的QPS上不去,于是又查看了下调用下游接口的QPS:
    在这里插入图片描述
    发现的接口的RPS高峰稳定在1700左右,而我机器的集群QPS配置的是3600,少了一半的量,然后看了下kafka的消费者容器的并发数,根据接口的耗时,也就是1s处理请求的个数 * 我们机器的数量 * kafka的并发数 * 线程池的maxPoolSize等于1700左右,所以猜测是跟线程池的maxPoolSize的大小和下游接口耗时有关系,下游接口耗时没办法优化,于是我将线程池的maxPoolSize改成动态配置(nacos或者apollo)便于动态调整该参数,
    将参数调大后,发现调用接口的QPS上来了,
    在这里插入图片描述
    高峰QPS稳定在2500左右,问题得已解决😄😄😄

    总结

    以上问题首先可以根据自己项目的逻辑用到了哪些组件,然后根据这些组件去排查,大概定位到是哪些地方出了问题,然后根据自己的猜测,列举几种解决方案,逐一去尝试,可能问题的答案就在其中,希望以上经验可以帮助到你!!!

    展开全文
  • 关于 ProcessThread ... 管理向线程池的提交任务,下发给线程去执行。 实现的基本功能(过程) ProcessThread 基本属性(任务队列、标记) 线程执行的逻辑(run) 线程停止(stop) Pool ...
  • Python线程池

    2022-05-07 14:14:01
    一、线程创建的开销与线程池 1.线程创建的开销 对操作系统来说,创建一个线程的代价是十分昂贵的,需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU 的缓存被清空,切换回来的时候还要重新...
  • ExecutorService就是要创建的线程池,案例ExecutorService pool = Executors.newFixedThreadPool(POOL_SIZE) 底层都是通过ThreadPoolExecutor实现的 public static ExecutorService newCachedThreadPool() { ...
  • java线程池thread pool使用总结

    千次阅读 2018-12-14 21:01:48
    一、线程池的用途 线程池主要是为了解决以下几个问题: 1、为多线程执行琐碎的任务提供支持 2、避免线程创建销毁过程的资源消耗 3、控制资源的使用,根据实际情况合理高效利用资源 4、 二、java提供的线程池...
  • 线程池(ThreadPool)

    千次阅读 2021-11-29 22:11:19
      线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与...
  • linux系统线程池

    2022-05-31 20:23:37
    本文简单介绍了线程池的概念和特点,对线程池的结构体和相关操作接口进行了设计,并提供了接口的具体实现,最后通过示例程序演示了线程池的运行过程。
  • python线程池threadpool

    千次阅读 2022-01-17 20:43:13
    今天在学习python进程与线程时,无意间发现了线程池threadpool模块 模块使用非常简单,前提是得需要熟悉线程池的工作原理。 我们知道系统处理任务时,需要为每个请求创建和销毁对象。当有大量并发任务需要处理时,再...
  • golang worker pool ,线程池 , 工作池 并发限制goroutine池。 限制任务执行的并发性,而不是排队的任务数。 无论排队多少任务,都不会阻止提交任务。 通过队列支持 golang 工作池公共库 支持最大任务数, 放到工作池...
  • 自己写的线程池控制台程序,类似ACE中的线程池的例子,只是多线程的运行更加健壮,不会出现当队列中无消息时,线程池迅速消失的BUG。VC6下通过编译,不依赖任何程序库,适合项目开发。
  • 高峰期秒杀场景的bug,同事原本处理了一个case,重置了状态,在finally里根据状态决定是否要补偿数据,但是用了这个Completable.runAsync,未指定线程池底层默认用了ForkJoinPool.commonPool() 同时高峰期详情页也有...
  • 线程池ForkJoinPool简介

    2020-04-11 21:35:31
    ForkJoinPool线程池最大的特点就是分叉(fork)合并(join),将一个大任务拆分成多个小任务,并行执行,再结合工作窃取模式(worksteal)提高整体的执行效率,充分利用CPU资源。 一. 应用场景 ForkJoinPool使用分治算法,...
  • 一、池化技术之线程池 实现线程池视频讲解,附源码:「链接」 什么是池化技术?简单来说就是优化资源的使用,我准备好了一些资源,有人要用就到我这里拿,用完了就还给我。而一个比较重要的的实现就是线程池。那么...
  • 手动创建线程池

    2021-08-17 15:46:02
    使用 JDK 自带的 Executors工具类 (图中蓝色框中的那个,这是独立于线程池继承关系图的工具类,类似于 Collections 和 Arrays) 可以直接创建以下种类的线程池 线程数量固定的线程池,此方法返回 ...
  • java 中四种线程池poolSize、corePoolSize、maximumPoolSizeExecutors 提供四种线程池:newCachedThreadPool :缓存线程池,如果线程池长度超过处理需要,可回收空闲线程,若无可回收,则新建线程。...
  • 【学习】线程池:关闭线程池的shutdown方法
  • c++ 线程池工具
  • 线程池之ForkJoinPool

    2021-05-06 23:06:25
    概述 ForkJoinPool分支/合并框架,就是在必要的情况下,将一个大任务拆分(fork)成若干个小任务(拆到不能再拆为止),在将一个个的小任务运算的结果进行Join汇总。
  • java 线程池 ForkJoinPool 的简单示例

    千次阅读 2019-01-29 15:03:05
    线程的实现方式 java 多线程之 extends Thread java 多线程之 implements Runnable java 多线程之 implements Callable ... 线程池的使用 ... java 线程池之 newScheduledTh...
  • Excutor 执行器接口,execute是执行方法, 使定义和运行可以分开,运行的方式可以自己去定义 ExcutorService 除了执行任务之外,还完善了整个任务执行的生命周期 ...线程池分为两类,分别是ThreadPoolExcu
  • ThreadPoolExecutor 手动创建线程池 ThreadPoolExecutor 手动创建线程池 ThreadPoolExecutor:最原始的创建线程池的方式 ThreadPoolExecutor 最多可以设置 7 个参数: 7 个参数代表的含义如下: corePoolSize...
  • vc写的简单的线程池 vc写的简单的线程池
  • Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。下面这张图完整描述了线程池的类体系结构。**Executor**一个接口...
  • 【python 多进程传参】pool.map() 函数传多参数

    万次阅读 多人点赞 2019-09-02 15:16:37
    相信很多人都用过,pool.map()函数,这个函数,有两个参数可以传,第一个参数传的是函数,第二个参数传的是数据列表。 那么怎么在第二个数据列表,多传几个参数呢,方法是通过对有多个参数的方法进行封装,在进程中...
  • Java 多线程编程常用的一个接口是 ExecutorService, 其实就一个线程池的接口,一般由两种方式创建线程池,一为 Executors 的工厂方法,二则创建 ForkJoinPool 实例,当然也有直接使用 ThreadPoolExecutor 的。...
  • Java 线程池会自动关闭吗?

    千次阅读 2021-02-28 16:37:57
    ThreadPoolExecutor 类(这是我们最常用的线程池实现类)的源码注释中有这么一句话:A pool that is no longer referenced in a program and has no remaining threads will be shutdown automatically.没有引用指向且...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 107,034
精华内容 42,813
关键字:

线程池pool