JDK自带线程池和七大参数

一、什么是线程池?

百度官方解释:线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。

一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。

任务调度以执行线程的常见方法是使用同步队列,称作任务队列。池中的线程等待队列中的任务,并把执行完的任务放入完成队列中。

  • 创建太多线程,将会浪费一定的资源,有些线程未被充分使用。

  • 销毁太多线程,将导致之后浪费时间再次创建它们。

  • 创建线程太慢,将会导致长时间的等待,性能变差。

  • 销毁线程太慢,导致其它线程资源饥饿。

jdk自带的构建线程池的几种方式:

1.newFileThreadPool:定长线程池,该线程池创建好,线程个数是固定的,如果线程没有构建,线程会待着任务执行被创建和执行,如果线程已经构建好了,此时任务才会被放到

LinkedBliockingQueue无界队列中存放,等待线程从LinkedBliockingQueue中去take出任务,然后执行。

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

2.newSingThreadPool:单例线程池,该线程池只有一个工作线程在处理任务,如果业务是顺序消费们可以采用该线程池,

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>(),
                                threadFactory));
}

3.newCachedThreadPool:缓存线程池,corePoolSize为0,当第一次提交任务到线程池时,会直接构建一个工作线程,Integer.MAX_VALUE:意味着线程数量可以无限大,

keepAliveTime为60S,60秒内没有任务进来,意味着线程空闲时间超过60S就会被杀死;如果在等待60秒期间有任务进来,他会再次拿到这个任务去执行,特点是:任务只要提交到该线程池就必然有工作线程处理

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

4.newScheduleThreadpool:定时线程池,创建一个定时线程池,即按一定的周期执行任务,即定时任务,或者设置定时时间,延迟执行任务,由于该线程池是继承ThreadPoolExecutor,所以本质上还是ThreadPoolExecutor线程池,只不过是在原来的基础上添加了定时功能,其原理是基于DelayQueue实现延迟执行,周期性执行,任务执行完毕,再次扔会到阻塞队列。

自定义线程池七大参数

1.int corePoolSize:核心线程数,创建线程池后不会立即创建核心线程,当有任务到达时才触发核心线程的创建;当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。核心线程在allowCoreThreadTimeout被设置为true时会超时并被回收,默认情况下不会被回收。

2.int maximumPoolSize:最大线程数,代表当前线程池中,一共可以有多少个工作线程。当线程数大于或等于corePoolSize,且任务队列已满时,线程池会创建新的线程,直到线程数量达到maxPoolSize。如果线程数已等于maxPoolSize,且任务队列已满,则已超出线程池的处理能力,线程池会按照rejectedExecutionHandler配置的处理策略进行处理线程。

3.long keepAliveTime: 非核心工作线程在阻塞队列位置等待的时间,当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize。如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0。

4.TimeUnit unit : 非核心工作线程在阻塞队列位置等待时间的单位

5. BlockingQueue<Runnable> workQueue 任务没有在核心工作线程处理时,任务先扔到阻塞队列中。阻塞队列,用来存储等待执行的任务,新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。这里的阻塞队列有以下几种选择:

(1.ArrayBlockingQueue:基于数组的有界阻塞队列,按FIFO排序;

(2.LinkedBlockingQueue:基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序;

(3. PriorityBlockingQueue:具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
(4.SynchronousQueue:一个不缓存任务的阻塞队列,也就是说新任务进来时,不会缓存,而是直接被调度执行该任务;

6.ThreadFactory threadFactory : 线程工厂,创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等。在构建线程的线程工作,可以设置thread 的一些信息

7.RejectedExecutionHandler handler: 当前线程池无法处理投递过来的任务时,执行当前的拒绝策略 ;拒绝策略有以下:

(1.AbortPolicy: 当前拒绝策略在无法处理任务时,会抛出一个异常

(2. CallerRunPolicy:当前拒绝策略在线程池无法处理任务时,会将任务交给调用者处理

(3.DiscardPolicy: 当前拒绝策略在无法处理任务时,会直接将任务丢掉

(4.DiscardOldestPolicy:当前拒绝策略在无法处理任务时,将队列中最早的任务丢掉,将当前再次尝试交给线程池处理

(5. 自定义Policy: 根据自己的任务,将任务扔到数据库,也可以做其他操作。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值