UNIX(多线程):22---几种常见的线程池

2021-02-03 12:15:27 浏览数 (2)

常见线程池

1、newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

从构造方法来看,它可以单独执行,也可以与周期线程池结合用。其任务队列是LinkedBlockingQueue,这是个无界的阻塞队列,因为线程池里只有一个线程,就确保所有的任务都在同一个线程中顺序执行,这样就不需要处理线程同步的问题。这类线程池适用于多个任务顺序执行的场景。

2、newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

一个固定大小的线程池,可以用于已知并发压力的情况下,对线程数做限制。

这类线程池的特点就是里面全是核心线程,没有非核心线程,也没有超时机制,任务大小也是没有限制的,数量固定,即使是空闲状态,线程不会被回收,除非线程池被关闭,从构造方法也可以看出来,只有两个参数,一个是指定的核心线程数,一个是线程工厂,keepAliveTime无效。任务队列采用了无界的阻塞队列LinkedBlockingQueue,执行execute方法的时候,运行的线程没有达到corePoolSize就创建核心线程执行任务,否则就阻塞在任务队列中,有空闲线程的时候去取任务执行。由于该线程池线程数固定,且不被回收,线程与线程池的生命周期同步,所以适用于任务量比较固定但耗时长的任务。

3、newCachedThreadPool

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

一个可以无限扩大的线程池,这类线程池的特点就是里面没有核心线程,全是非核心线程,其maximumPoolSize设置为Integer.MAX_VALUE,线程可以无限创建,当线程池中的线程都处于活动状态的时候,线程池会创建新的线程来处理新任务,否则会用空闲的线程来处理新任务,这类线程池的空闲线程都是有超时机制的,keepAliveTime在这里是有效的,时长为60秒,超过60秒的空闲线程就会被回收,当线程池都处于闲置状态时,线程池中的线程都会因为超时而被回收,所以几乎不会占用什么系统资源。任务队列采用的是SynchronousQueue,这个队列是无法插入任务的,一有任务立即执行,所以CachedThreadPool比较适合任务量大但耗时少的任务。

4、newScheduledThreadPool

创建一个定长线程池,支持定时及周期性任务执行。

可以延时启动,定时启动的线程池,适用于需要多个后台线程执行周期任务的场景。

这类线程池核心线程数量是固定的,好像和FixThreadPool有点像,但是它的非核心线程是没有限制的,并且非核心线程一闲置就会被回收,keepAliveTime同样无效,因为核心线程是不会回收的,当运行的线程数没有达到corePoolSize的时候,就新建线程去DelayedWorkQueue中取ScheduledFutureTask然后才去执行任务,否则就把任务添加到DelayedWorkQueue,DelayedWorkQueue会将任务排序,按新建一个非核心线程顺序执行,执行完线程就回收,然后循环。任务队列采用的DelayedWorkQueue是个无界的队列,延时执行队列任务。综合来说,这类线程池适用于执行定时任务和具体固定周期的重复任务。

5、newWorkStealingPool

一个拥有多个任务队列的线程池,可以减少连接数,创建当前可用cpu数量的线程来并行执行。

比如java程序,假设共有三个线程同时执行, A, B, C,

* 当A,B线程池尚未处理任务结束,而C已经处理完毕,则C线程会从A或者B中窃取任务执行,这就叫工作窃取

* 假如A线程中的队列里面分配了5个任务,而B线程的队列中分配了1个任务,当B线程执行完任务后,它会主动的去A线程中窃取其他的任务进行执行

* WorkStealingPool 背后是使用 ForkJoinPool实现的

我在上一篇文章中提到的就是newFixedThreadPool的模型,那么我在这篇文章里将提供newSingleThreadExecutor模型的代码,其实当你会了newFixedThreadPool,再看newSingleThreadExecutor不难。

代码语言:javascript复制
//! @file task_base.h
//! @brief 线程


#ifndef _TASK_BASE_H_
#define _TASK_BASE_H_

#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#else
#include <pthread.h>
#endif

namespace utils {


    //! @class Task_Base
    //! @brief 线程类
    class Task_Base
    {
    public:
        Task_Base();
        virtual ~Task_Base();

        //! 启动线程
        int activate();

        //! 等待线程
        int wait();

        //! 线程函数
        virtual int svc() = 0;

    private:
        //! 线程函数
#ifdef WIN32
        static unsigned __stdcall thread_proc(void* param);
#else
        static void* thread_proc(void* param);
#endif

    private:
        //! 线程id
#ifdef WIN32
        HANDLE m_thread;
#else
        pthread_t m_thread;
#endif
    };


} // namepsace utils

#endif // _TASK_BASE_H_

获取相关 单线程化的线程池 源码,可关注公众号之后,在后台回复“单线程化线程池源码”获取下载链接

0 人点赞