2020 年第一篇,Go!


Executor 英文意思是执行者,可以看出它的作用是提交和执行任务接口,也可以理解为是线程池。


Executor 有一个子接口 ExecutorService,ExecutorService 可以管理和终止任务的方法,可以追踪异步任务的进度的 Executor。


Executors 是线程池的工厂类,提供静态工具方法。使用 Executors 可以方便地创建各种类型的线程池。但是由于 Executors 创建的线程池内部很多地方用到了***任务队列,在高并发场景下,***任务队列会接收过多的任务对象,导致 JVM 抛出OutOfMemoryError,整个 JVM 服务崩溃,影响严重。所以很多公司已经不建议使用 Executors 去创建线程。


简单介绍下 Executors 的使用:

newFixedThreadPool:创建定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程newCachedThreadPool:创建可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制newScheduledThreadPool:创建定长线程池,可执行周期性的任务newSingleThreadExecutor:创建单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行newSingleThreadScheduledExecutor:创建单线程可执行周期性任务的线程池newWorkStealingPool:任务可窃取线程池,不保证执行顺序,当有空闲线程时会从其他任务队列窃取任务执行,适合任务耗时差异较大


JDK 提供的线程池相关的工具类中,最核心的是 ThreadPoolExecutor。它最复杂的构造函数有 7 个参数:

public ThreadPoolExecutor(int corePoolSize,    int maximumPoolSize,    long keepAliveTime,    TimeUnit unit,    BlockingQueue<Runnable> workQueue,    hreadFactory threadFactory,    RejectedExecutionHandler handler)


参数说明: 

corePoolSize:线程池保有的最小线程数maximumPoolSize:线程池创建的最大线程数keepAliveTime:一个线程空闲了 keepAliveTime * unit 这么长时间,且线程池的线程数大于 corePoolSize ,那么这个空闲的线程就要被回收了unit:keepAliveTime 的时间单位workQueue:任务队列threadFactory:线程工厂对象,可以自定义如何创建线程,如给线程指定 namehandler:自定义任务的拒绝策略。线程池中所有线程都在忙碌,且任务队列已满,线程池就会拒绝接收再提交的任务。handler 就是拒绝策略,包括 4 种(即 RejectedExecutionHandler 接口的 4个实现类)    AbortPolicy:默认的拒绝策略,throws RejectedExecutionException    CallerRunsPolicy:提交任务的线程自己去执行该任务    DiscardPolicy:直接丢弃任务,不抛出任何异常    DiscardOldestPolicy:丢弃最老的任务,加入新的任务


使用示例:

package constxiong.interview;
import java.util.concurrent.Executor;import java.util.concurrent.Executors;import java.util.concurrent.SynchronousQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;
/** * 测试 ThreadPoolExecutor 创建线程池 * @author ConstXiong */public class TestThreadPoolExecutor {
 public static void main(String[] args) {    testSubmitTask();  }
 /**   * 测试使用 ThreadPoolExecutor 创建线程池,并向线程池提交任务   */  private static void testSubmitTask() {    int corePoolSize = 1;//最小线程数    int maximumPoolSize = 2;//最大线程数    long keepAliveTime = 1000L;//1000个单位时间    Executor exector = new ThreadPoolExecutor(corePoolSize,        maximumPoolSize,        keepAliveTime,        TimeUnit.MILLISECONDS,        new SynchronousQueue<Runnable>(),//可以修改队列:有界队列、***队列、有优先级的队列        Executors.defaultThreadFactory(),//线程工程对象,可以定义如何创建线程        new ThreadPoolExecutor.AbortPolicy()); //任务队列已满,线程池决绝策略    for (int i = 0; i < 5; i++) {      exector.execute(() -> {        System.out.println(Thread.currentThread().getName());      });    }  }
}


更多相关文章

  1. Redis为什么又引入了多线程?作者也逃不过“真香定理”?
  2. 详解第三种创建线程的方式-Callable接口
  3. 聊一聊面试中常问的java阻塞队列
  4. java线程相关面试题(第一版)
  5. Java线程之线程的调度-让步
  6. 栈和队列就是这么简单

随机推荐

  1. CooradicatoarLayout 介绍
  2. 判断应用是安装还是卸载了
  3. android 3.0以上对usb设备的访问USB
  4. 导入android-support-v7-appcompat出现问
  5. Android error:Lint found fatal errors
  6. 去除android锁屏
  7. 手机壁纸设置相关
  8. android中属性动画
  9. android 得到唯一码和电话号码
  10. 问题:plugin with id 'android' not foun