前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java 线程池

java 线程池

作者头像
java404
发布2018-05-18 14:34:54
9270
发布2018-05-18 14:34:54
举报
文章被收录于专栏:java 成神之路java 成神之路

概述

  1. 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务
  2. 可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)
  3. 线程池使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务,减少创建和销毁线程的次数。

java 中提供了3种实现

  1. ThreadPoolExecutor:标准线程池
  2. ScheduledThreadPoolExecutor:支持延迟任务的线程池
  3. ForkJoinPool:类似于ThreadPoolExecutor,但是使用work-stealing模式,其会为线程池中的每个线程创建一个队列,从而用work-stealing(任务窃取)算法使得线程可以从其它线程队列里窃取任务来执行。既如果自己的任务处理完成了,则可以去忙碌的工作线程那里窃取任务执行。

1.ThreadPoolExecutor

代码语言:javascript
复制
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler){
 ...... 
}
  • corePoolSize:核心线程池大小,线程池维护的线程最少线程。
  • maximumPoolSize:线程池最大大小。
  • keepAliveTime:线程池中线程的最大空闲时间,如果线程池中的线程个数大于corePoolSize,并且线程空闲时间超过该时间的线程会被回收。
  • unit: 线程池维护线程所允许的空闲时间的单位、可选参数值为:TimeUnit中的几个静态属性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。
  • workQueue: 线程池中存放工作任务的队列。常用的是:java.util.concurrent.ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue
  • threadFactory: 线程工厂,提供创建新线程的功能。ThreadFactory是一个接口,只有一个方法,通过线程工厂可以对线程的一些属性进行定制。
  • handler:线程池中的数量大于maximumPoolSize,对拒绝任务的处理策略,默认值ThreadPoolExecutor.AbortPolicy()。
Executors 提供了3个工厂方法创建 ThreadPoolExecutor
  1. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
代码语言:javascript
复制
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
}
  1. newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
代码语言:javascript
复制
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
}
  1. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
代码语言:javascript
复制
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
}

2. ScheduledThreadPoolExecutor

我们通过查看ScheduledThreadPoolExecutor的源代码,可以发现ScheduledThreadPoolExecutor继承了ThreadPoolExecutor。

代码语言:javascript
复制
public ScheduledThreadPoolExecutor(int corePoolSize,
                                   ThreadFactory threadFactory,
                                   RejectedExecutionHandler handler) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue(), threadFactory, handler);
}

从构造中发现ScheduledThreadPoolExecutor线程池其实是调用了ThreadPoolExecutor构造进行实现的,只是ThreadPoolExecutor使用的工作队列是java.util.concurrent.ScheduledThreadPoolExecutor.DelayedWorkQueue通过名字我们都可以猜到这个是一个延时工作队列。 因为ScheduledThreadPoolExecutor的最大线程是Integer.MAX_VALUE,而且根据源码可以看到execute和submit其实都是调用schedule这个方法,而且延时时间都是指定为0,所以调用execute和submit的任务都直接被执行。

Executors 也提供了ScheduledThreadPoolExecutor创建方式
代码语言:javascript
复制
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

ScheduledThreadPoolExecutor 提供了3种延迟执行策略

  1. schedule(commod,delay,unit) ,这个方法是说系统启动后,需要等待多久执行,delay是等待时间。只执行一次,没有周期性。
  2. scheduleAtFixedRate(commod,initialDelay,period,unit),固定速率执行周期任务。这个是以period为固定周期时间,按照一定频率来重复执行任务,initialDelay是说系统启动后,需要等待多久才开始执行。
  3. scheduleWithFixedDelay(commod,initialDelay,delay,unit),固定延迟执行周期任务。这个是以delay为固定延迟时间,按照一定的等待时间来执行任务,initialDelay意义与上面的相同。

3. ForkJoinPool

在Java 7中引入了一种新的线程池:ForkJoinPool。 它同ThreadPoolExecutor一样,也实现了Executor和ExecutorService接口。它使用了一个无限队列来保存需要执行的任务,而线程的数量则是通过构造函数传入,如果没有向构造函数中传入希望的线程数量,那么当前计算机可用的CPU数量会被设置为线程数量作为默认值。

Executors 提供了 ForkJoinPool 的创建方式
代码语言:javascript
复制
public static ExecutorService newWorkStealingPool() {
    return new ForkJoinPool
        (Runtime.getRuntime().availableProcessors(),
         ForkJoinPool.defaultForkJoinWorkerThreadFactory,
         null, true);
}

并发数默认为当前系统cpu个数。

代码语言:javascript
复制
public static ExecutorService newWorkStealingPool(int parallelism) {
    return new ForkJoinPool
        (parallelism,
        ForkJoinPool.defaultForkJoinWorkerThreadFactory,
        null, true);
}

也可以指定并行数。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.10.31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • java 中提供了3种实现
  • 1.ThreadPoolExecutor
    • Executors 提供了3个工厂方法创建 ThreadPoolExecutor
    • 2. ScheduledThreadPoolExecutor
      • Executors 也提供了ScheduledThreadPoolExecutor创建方式
      • 3. ForkJoinPool
        • Executors 提供了 ForkJoinPool 的创建方式
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档