线程池

一、我们为什么使用线程池?

       我们在处理的任务较少时,可以手动通过继承Thread类,实现Runnable接口来进行创建线程去处理,但是在高并发的场景下,需要处理的任务量很多,频繁的创建线程会大大降低系统的效率。此时,我们就可以使用线程池,也是企业中应用最多的,线程池中的线程执行完一个任务后可以复用,并不被销毁。合理的使用线程池可以达到:

1. 减少资源的开销。通过复用线程,降低创建销毁线程造成的消耗。

2. 多个线程并发执行任务,提高系统的响应速度。

3. 可以统一的分配,调优和监控线程,提高线程的可控性。

二、创建线程池的五大参数

我们在使用线程池来创建线程:

public static void main(String[] args) {

        ExecutorService threadPool = Executors.newFixedThreadPool(5);
//        Executors.newSingleThreadExecutor();
//        Executors.newCachedThreadPool();
//        Executors.newScheduledThreadPool(5);

        try {
            for (int j = 0; j < 10; j++) {
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"正在运行");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }

可以使用newFixedThreadPool、newSingleThreadExecutor、newCachedThreadPool、newScheduledThreadPool这四种方式来创建线程池,下面追溯到源码来看看是怎么实现的?

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



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



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


//newScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }
前三种方式都是ThreadPoolExecutor类的构造方法去创建线程的,构造方法中有5个参数,每种方式的入参是不同的。通过参数值的不同来分析每种方式的特点。下面我们来看每个参数表示什么
public ThreadPoolExecutor(int corePoolSize,  //核心线程数
                              int maximumPoolSize,   //最大线程数
                              long keepAliveTime,   //线程存活时间
                              TimeUnit unit,    //时间单位
                              BlockingQueue<Runnable> workQueue //任务队列,已经提交       但是未被执行的任务
) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

核心线程数:在创建了线程池后,有任务请求时,就会安排线程去执行任务,当线程池中的线程数超过corePoolSize后,将请求的任务放在任务队列中;

最大线程数:线程池中允许容纳同时执行的最大线程数,必须大于等于1;

线程存活时间:如果当前线程池中的线程数超过corePoolSize时,多余的线程空闲时间超过keepAliveTime时,就会被销毁,直到只剩下核心线程数为止;

任务队列:存放已经提交但是没有被执行的任务,常见的3种队列:

LinkedBlockingQueue:无界队列;SynchronousQueue:直接队列;ArrayBlockingQueue:有界队列

创建线程池的方式特点:

根据三种创建线程池方式的参数不同,我们来分析各自的特点:

newFixedThreadPool传入的任务队列是,LinkedBlockingQueue无界队列,可以存放无限制的任务请求,当请求越来越多并且无法及时处理完毕时,出现请求堆积,占用大量内存,可能会出现OOM;

newsingleThreadExecutor:和上边的方式基本相同,但是直接将核心线程数设置为1,但是也有同样的问题,可能出现占用大量内存的情况;

newCachedThreadPool:将最大线程数设置成最大值,可能会出现OOM问题。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值