Java并发基础(2)------线程池

线程池的作用

  1. 每次创建和关闭线程都会需要花费时间(会引起系统上下文的切换),如果为每一个任务都创建一个线程,就可能会出现创建和关闭的时间大于单线程运行的时间,失去多线程的优势。

  2. 为了避免频繁的创建和销毁线程,我们可以将创建的线程进行复用,使用线程池去维护一定活跃的线程,在需要使用到线程的时候,直接从线程池中取,无需重新创建,使用完也无需关闭线程,直接将其归还至线程池中,减少这部分的性能消耗。

Executor框架

  1. 类与接口

2.Executor框架提供以下五种创建线程池的静态工厂方法

  • newFixedThreadPool()方法会返回一个具有固定数量线程的线程池,该线程池中的线程数量始终不变。如果有一个先的任务提交时,如果线程池中有空闲的线程则立即执行。如果没有的话会被暂存在一个任务队列中,等待有空闲线程的时候才会执行。
  • newSingleThreadPool()方法会返回一个只有一个线程的线程池。若有多余一个的任务被提交到任务队列中,任务会被保存在任务队列中。等到线程空闲时,按先入先出的顺序执行队列中的任务。
  • newCacheThreadPool()该方法返回一个可根据实际情况调整数量的线程池,线程池的数量不确定,如果有空闲线程可以复用时,会优先使用可复用的线程。若所有的线程都在工作,又有新的任务体积搜,则会创建先的线程处理任务,所有线程在当前任务执行完毕后,将返回线程池进行复用(注意:newCachedThreadPool()线程池里面的线程等上个线程执行完成才可以复用线程,否则它会一直create线程。)
  • newSingleThreadPoolScheduledExecutor()方法,周期性的执行某个任务
  • newScheduledThreadPool()方法,该方法也返回一个ScheduledExxecutorService对象,但该线程可以指定线程数量
  1. ThreadExecutor

参数解析:

  • corePoolSize:指定了线程池中线程的数量。

  • maximumPoolSize:指定了线程池中最大的线程数。

  • keepAliveTime:当线程数超过corePoolSize时,多余空闲线程的存活时间。即,超过corePoolSize的空闲线程,会在多长时间内,会被销毁。

  • unit:KeepAliveTime的时间单位,使用TimeUnit类。

  • workQueue:任务队列,被提交但尚未被执行的任务。

  • threadFactory:线程工厂,用于创建线程,一般使用默认即可。

  • handler:拒绝策略,当任务太多来不及处理,如何拒绝任务。

workQueue

  1. SynchronousQueue(直接提交的队列,newCachedThreadPool使用该队列),他是一个特殊的BlockingQueue,它没有容量,每一个插入操作都需要等待一个相应的删除操作,反之,每一个删除操作都需要等待一个插入的操作,提交的任务不会真正的保存,而总是将新任务提交给线程执行,如果没有空闲的进程,则尝试创建新的进程,如果进程数量已经达到最大值,则执行拒绝策略。因此,使用SynchronousQueue队列,通常要设置很大的maximumPoolSize值,否则很容易执行拒绝策略。

  2. ArrayBlockingQueue(有界的任务队列),ArayBlockingQueue 的构造函数必须带一个容量参數,表示该队列的最大容量,如下所示当使用有界的任务队列时,若有新的任务需要执行,如果线程池的实际线程数小于corePoolSize,则会优先创建新的线程,若大于corePoolSize,则会将新任务加入等待队列。若等待队列已满,无法加入,则在总线程数不大于maximumPoolSize的前提下,创建新的进程执行任务。若大于maximumPoolSize,则执行拒绝策略。可见,有界队列仅当在任务队列装满时,才可能将线程数提升到corePoolSize以上,换言之,除非系统非常繁忙,否则确保核心线程数维持在在corePoolSize。

  3. LinkedBlockingQueue(无界的任务队列,newFixedThreadPool和newSingleThreadExecutor使用该队列),与有界队列相 比,除非系统资源耗尽,否则无界的任务队列不存在任务入队失败的情况。当有新的任务到来,系统的线程数小于corePoolSize时,线程池会生成新的线程执行任务,但当系统的线程数达到corePoolSize后,就不会继续增加。若后续仍有新的任务加入,而又没有空闲的线程资源,则任务直接进入队列等待。若任务创建和处理的速度差异很大,无界队列会保持快速增长,直到耗尽系统内存。

  4. PriorityBlockingQueue(优先任务队列是带有执行优先级的队列),可以控制任务的执行先后顺序,它是一个特殊的无界队列。无论是有界队列ArrayBlockingQueue,还是未指定大小的无界队列LinkedBlockingQueue 都是按照先进先出算法处理任务的。而PriorityBlockingQueue则可以根据任务自身的优先级顺序先后执行,在确保系统性能的同时,也能有很好的质量保证(总是确保高优先级的任务先执行)。

handler 拒绝策略

猜你喜欢

转载自juejin.im/post/5cfe0c0f6fb9a07f03572f20
今日推荐