线程池

线程池的作用

  1. 限制系统中执行线程的数量,防止不断开辟新线程而造成的资源枯竭;
  2. 线程池维护着一个线程的集合,在需要执行新的任务时重用这些线程而不是新建一个线程(提高线程复用,减少性能开销)。

如何创建线程池

8204f4bfa0cfb7b5bea3fff6762863817b3.jpg

参数解释:

  1. corePoolSize:核心池大小,即在没有任务执行时线程池的大小,并且只有在工作队列满了的情况下才会创建超出这个数量的线程(但小于最大池大小)。
  2. maximumPoolSize:最大池大小,可同时活动的线程数的上限,若空闲时,会销毁超出核心池大小的多余线程。
  3. keepAliveTime:空闲线程超时时间,若一个线程已经闲置的时间超过了存活时间,它将成为一个被回收的候选者,若当前的池大小已经超过了核心池大小,这个线程会被终止掉。
  4. BlockingQueue:任务阻塞队列,当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务。有如下几种:

    1.无限队列:newFixedThreadPool和newSingleThreadExecutor默认使用一个无限的LinkedBlockingQueue阻塞队列,若所有工作者线程都处于忙碌,任务将会在队列中等候,若任务持续快速地到达,队列也会无限制地增加。

    2.有限队列:为了避免资源被耗尽,线程池也经常使用有限队列,如ArrayBlockingQueue或有界的LinkedBlockingQueue;当队列满时,新来的任务会使用饱和策略处理。

    3.同步移交:同步移交适合线程池无限或者可以接受任务被拒绝的情况,newCachedThreadPool就使用同步移交方式。使用SychronousQueue来避免任务排队,他不是一个真正的队列,可以将任务从生产者移交给工作者。

  5. ThreadFactory:线程工厂。
  6. RejectedExecutionHandler:拒绝策略,有如下几种:

    1.中止(abort):默认的饱和策略,会抛出未检查的拒绝执行异常RejectedExecutionException,调用者捕获该异常做适当处理。

    2.遗弃(discard):丢弃最新提交的任务。

    3.遗弃最旧的(discard-oldest):丢弃本应该接下来就要执行的任务,并尝试去重新提交新任务,若是优先级队列,则丢弃优先级最高的任务,因此不能混合使用遗弃最旧的饱和策略和优先级队列。

    4.调用者运行(caller-runs):既不会丢最新提交的任务,也不会抛出异常,会把最新提交的任务推回到调用者,由生产者线程执行,一方面给工作者线程时间来追赶进度,另一方面减慢了生产者提交新任务的速度。

Executors提供了四种创建好的线程池:

  1. newFixedThreadPool:创建一个固定长度的线程池,每当提交一个任务时就创建一个线程,直到达到线程池的最大数量,此时线程池的规模将不再变化。
    public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
    }

     

  2. newSingleThreadExecutor:单线程线程池,能确保依照任务在队列中的顺序串行执行。
    public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
    }

     

  3. newCachedThreadPool:创建一个可以无限扩张的线程池。
    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
    }

     

  4. newScheduledThreadPool:创建一个固定长度的线程池,以延时或定时的方式来执行任务,类似于Timer。
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
            return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    

     

示例

public class ThreadPoolTest {
    public static void main(String[] args) {
        ExecutorService threadPool1=new ThreadPoolExecutor(
                5,
                5,
                0L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(1024));

        ExecutorService threadPool2=Executors.newFixedThreadPool(5);
        ExecutorService threadPool3=Executors.newCachedThreadPool();
        ExecutorService threadPool4=Executors.newScheduledThreadPool(3);
        ExecutorService threadPool5=Executors.newSingleThreadExecutor();

    }
}

更多示例:https://blog.csdn.net/achuo/article/details/80623893

阿里规约中不建议使用Executors去创建线程池,而是通过ThreadPoolExecutor,因为它的弊端在于:

  1. newFixedThreadPool和newSingleThreadExecutor默认使用一个无限的LinkedBlockingQueue阻塞队列,堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
  2. newCachedThreadPool和newScheduledThreadPool的线程最大数是Integer.MAX_VALUE,可能会创建非常多的线程,甚至OOM。

阿里规约中给出的创建线程池的示例:

ThreadFactory namedThreadFactory=new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
        ExecutorService threadPool6=new ThreadPoolExecutor(
                5,
                200,
                0L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

其中ThreadFactoryBuilder来源于Google的guava包。

转载于:https://my.oschina.net/u/2286010/blog/3074432

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值