跳到主要内容

线程池的使用

· 阅读需 4 分钟
flankx

1、进程和线程的区别

  • 进程:进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。
  • 线程:线程是一条执行路径,是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。

2、线程池:ThreadPoolExecutor

线程池参数类型参数理解
corePoolSizeint核心线程数线程数定义了最小可以同时运行的线程数量
maximumPoolSizeint当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
workQueueBlockingQueue<Runnable>当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。
keepAliveTimelong当线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了keepAliveTime才会被回收销毁。
unitTimeUnitkeepAliveTime 参数的时间单位。
threadFactoryThreadFactoryexecutor 创建新线程的时候会用到。
handlerRejectedExecutionHandler饱和策略。

3、线程池大小的确定

  • 有一个简单并且适用面比较广的公式:
  • CPU 密集型任务(N+1): 这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响。一旦任务暂停,CPU 就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间。
  • I/O 密集型任务(2N): 这种任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线程在处理 I/O 的时间段内不会占用 CPU 来处理,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中,我们可以多配置一些线程,具体的计算方法是 2N。