线程池技术的使用

线程池技术的使用

1.创建线程池(不使用)

ExecutorService threadPool1 = Executors.newFixedThreadPool(3);// 固定大小
ExecutorService threadPool2 = Executors.newCachedThreadPool();//可以弹性伸缩的线程池,遇强则强 ExecutorService threadPool3 = Executors.newSingleThreadExecutor();// 只有一个
这种办法创建的线程池,存在弊端(阿里原话)
1)FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool 和 ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

底层这几种创建方式都是一样的:

Executors.newFixedThreadPool(3)底层为:
 return new **ThreadPoolExecutor**(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
                                      
Executors.newCachedThreadPool()底层为:
                                      return new **ThreadPoolExecutor**(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
                                      
Executors.newSingleThreadExecutor()底层为:
												new **ThreadPoolExecutor**(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>())

LinkedBlockingQueue都没指定大小那默认就是最大整数。

2.推荐创建方法(推荐)

//获取当前计算机或服务器的线程数,

    public class ThreadPoolTec {
    public static void main(String[] args) {
        //推荐的线程池的创建方法
        /**
         * 最多可以存在的人,maximumPoolSize + LinkedBlockingDeque的容量
         *触发非活跃线程变为活跃的方法是:当前任务数量大于最大线程池容量,每超一个则激活一个,直到都被激活
         * // 拒绝策略说明:
         * // 1. AbortPolicy (默认的:队列满了,就丢弃任务抛出异常!)
         * // 2. CallerRunsPolicy(哪来的回哪去? 谁叫你来的,你就去哪里处理)
         * // 3. DiscardOldestPolicy (尝试将最早进入对立与的人任务删除,尝试加入队列)
         * // 4. DiscardPolicy (队列满了任务也会丢弃,不抛出异常)
         */
      Integer processors = Runtime.getRuntime().availableProcessors());
        ExecutorService threadPool = new ThreadPoolExecutor(
                2,//核心活跃线程数,类比银行两个柜台一直保持营业
                processors ,//线程池最大大小,类比银行共5个柜台可以营业
                2L,//超时回收空闲的线程,类比有三个非活跃线程处于活跃状态,在一定时间还未接到任务就进入非活跃状态(就是不营业了)
                TimeUnit.SECONDS,//时间单位
                new LinkedBlockingDeque<>(3),//存放等待任务的队列,类比为银行的候客区,不指定大小的话就是最大整数
                Executors.defaultThreadFactory(),// 线程工厂,不修改!用来创建
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略,即候客区满了,不再允许其他人排队了

        );

        try {
            for(int j=1;j<=8;j++){
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"is running………………");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }
}

这里几点说明:
1.创建线程池最大线程数与运行机器的线程数一致是最大利用资源。
Runtime.getRuntime().availableProcessors());就是获取当前机器的最大线程数
2.任务排队的队列要指定大小,new LinkedBlockingDeque<>(3),这样就不会太多等待的。
3.绝句策略依具体要求而定,我采用new ThreadPoolExecutor.CallerRunsPolicy()
4.注意多线程的执行,采用lamda方式写得:
for(int j=1;j<=8;j++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+“is running………………”);
});
}

ThreadPoolExecutor 底层工作原理:在这里插入图片描述
拒绝策略流程图:
在这里插入图片描述

发布了67 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/m0_37635053/article/details/104558725