java线程池推荐使用方式

475 阅读3分钟
/**
 * @program: thread_dome
 * @description: 线程池  推荐使用 ThreadPoolExecutor,自己定义线程池
 *  <p>
 *  以下接口阿里不推荐使用:
 *  --FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
 *  --CachedThreadPool和ScheduledThreadPool:允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
 *  Executors.newCachedThreadPool() -->创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,被{@link TestPool#getCacheThreadPool()}代替
 *  Executors.newFixedThreadPool()  -->创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待{@link TestPool#getNewFixedThreadPool()}代替
 *  Executors.newSingleThreadExecutor() --> 创建一个单线程的线程池,可保证所有任务按照指定顺序{@link TestPool#getPriorityPool()}代替
 *  Executors.newScheduledThreadPool() -->创建一个周期性的线程池,支持定时及周期性执行任务{@link TestPool#getScheduledThreadPool()} ()}代替
 *  </p>
 * 执行策列:
 * (1)当线程数小于核心线程数时,创建线程。
 * (2)当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
 * (3)当线程数大于等于核心线程数,且任务队列已满:a.若线程数小于最大线程数,创建线程。b.若线程数等于最大线程数,抛出异常,拒绝任务。
 * <p>
 * 拒绝策略:
 * 1、AbortPolicy策略:该策略会直接抛出异常,阻止系统正常工作;
 * 2、CallerRunsPolicy策略:如果线程池的线程数量达到上限,该策略会把任务队列中的任务放在调用者线程当中运行;
 * 3、DiscardOledestPolicy策略:该策略会丢弃任务队列中最老的一个任务,也就是当前任务队列中最先被添加进去的,马上要被执行的那个任务,并尝试再次提交;
 * 4、DiscardPolicy策略:该策略会默默丢弃无法处理的任务,不予任何处理。当然使用此策略,业务场景中需允许任务的丢失;
 * <p>
 * 线程池线程数量:
 * Ncpu=CPU数量
 * Ucpu=目标CPU的使用率,0<=Ucpu<=1
 * W/C=任务等待时间与任务计算时间的比率
 * Nthreads = Ncpu*Ucpu*(1+W/C)
 *
 * @author: MT.xwq
 * @create: 2022/02/22
 **/


public class TestPool {
    public static void main(String[] args) {

//        ThreadPoolExecutor pool = getCacheThreadPool();
//        ThreadPoolExecutor pool = getNoQueuePool();
//        ThreadPoolExecutor pool = getWaitingPool();
//        ThreadPoolExecutor pool = getPriorityPool(); //优先队列
//        ThreadPoolExecutor pool = getThreadFactoryPool();
//        ThreadPoolExecutor pool = getThreadPoolExecutor();
        ThreadPoolExecutor pool = getDelayThreadPool(); //延时队列
        for (int i = 0; i < 5; i++) {
//            pool.execute(new ThreadTask());
            //优先队列线程池
//            pool.execute(new ThreadTask(i));
            //延时队列线程池
            Random ran = new Random(i);
            pool.execute(new DelayThreadTask(Long.valueOf(ran.nextInt(10))));
        }
        //定时任务线程
//        ScheduledThreadPoolExecutor scheduledThreadPool = getScheduledThreadPool();
//        scheduledThreadPool.schedule(new ThreadTask(), 2, TimeUnit.SECONDS); //延时2秒后执行,只执行1次
//        scheduledThreadPool.scheduleAtFixedRate(new ThreadTask(),2, 1,TimeUnit.SECONDS); //延时循环执行,首次执行延时2秒,后面是1秒
        pool.shutdown();
    }

    /**
     * corePoolSize:指定了线程池中的线程数量,它的数量决定了添加的任务是开辟新的线程去执行,还是放到workQueue任务队列中去;
     * maximumPoolSize:指定了线程池中的最大线程数量,这个参数会根据你使用的workQueue任务队列的类型,决定线程池会开辟的最大线程数量;
     * keepAliveTime:当线程池中空闲线程数量超过corePoolSize时,多余的线程会在多长时间内被销毁;
     * unit:keepAliveTime的单位
     * workQueue:任务队列,被添加到线程池中,但尚未被执行的任务;它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列几种;
     * threadFactory:线程工厂,用于创建线程,一般用默认即可;
     * handler:拒绝策略;当任务太多来不及处理时,如何拒绝任务;
     * 队列缓存为2,策略为直接拒绝
     *
     * @return
     */
    private static ThreadPoolExecutor getCacheThreadPool() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 10000, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue(1), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        return threadPoolExecutor;
    }

    private static ThreadPoolExecutor getNewFixedThreadPool() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 2, 10000, TimeUnit.MILLISECONDS,
                new SynchronousQueue(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        return threadPoolExecutor;
    }

    /**
     * 没有队列的线程池
     * SynchronousQueue是一个特殊的BlockingQueue,它没有容量,没执行一个插入操作就会阻塞,需要再执行一个删除操作才会被唤醒
     *
     * @return
     */
    private static ThreadPoolExecutor getNoQueuePool() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 10000, TimeUnit.MILLISECONDS,
                new SynchronousQueue(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        return threadPoolExecutor;
    }

    /**
     * 获取一直等待的队列
     * LinkedBlockingQueue没有大小限制
     *
     * @return
     */
    private static ThreadPoolExecutor getWaitingPool() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 10000, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        return threadPoolExecutor;
    }

    /**
     * 优先队列线程池
     * PriorityBlockingQueue优先队列,可排序
     *
     * @return
     */
    private static ThreadPoolExecutor getPriorityPool() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, 1, 10000, TimeUnit.MILLISECONDS,
                new PriorityBlockingQueue<>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        return threadPoolExecutor;
    }

    /**
     * 获取自定义工厂的线程池
     *
     * @return
     */
    private static ThreadPoolExecutor getThreadFactoryPool() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 10000, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                //线程命名
                return new Thread(r, String.format("[线程池-%s]", r.hashCode()));
            }
        }, new ThreadPoolExecutor.AbortPolicy());
        return threadPoolExecutor;
    }

    /**
     * 扩展线程池
     *
     * @return
     */
    private static ThreadPoolExecutor getThreadPoolExecutor() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, 1, 10000, TimeUnit.MILLISECONDS,
                new PriorityBlockingQueue<>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()) {
            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                System.out.println(String.format("准备执行,第%s优先级线程:", ((ThreadTask) r).getPriority()));
            }

            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                System.out.println(String.format("第%s优先级线程执行完成:", ((ThreadTask) r).getPriority()));
            }

            @Override
            protected void terminated() {
                System.out.println("线程池退出了");
            }
        };
        return threadPoolExecutor;
    }

    /**
     * 由线程控制延时的线程池
     * @return
     */
    private static ThreadPoolExecutor getDelayThreadPool(){
        DelayQueue delayThreadTasks = new DelayQueue<>();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, 4, 10000, TimeUnit.MILLISECONDS,
                delayThreadTasks, Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        return threadPoolExecutor;
    }

    /**
     * 定时任务线程
     */
    private static ScheduledThreadPoolExecutor getScheduledThreadPool(){
        ScheduledThreadPoolExecutor se=new ScheduledThreadPoolExecutor(2);
        return se;
    }


    static class ThreadTask implements Runnable, Comparable<ThreadTask> {
        private int priority;

        public ThreadTask(int priority) {
            this.priority = priority;
        }

        public ThreadTask() {
        }

        public int getPriority() {
            return priority;
        }

        public void setPriority(int priority) {
            this.priority = priority;
        }

        @Override
        public int compareTo(ThreadTask o) {
            //反序
            return this.priority > o.priority ? -1 : 1;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(String.format("我是线程:%s, priority:%s", Thread.currentThread().getName(), priority));
        }
    }

    static class DelayThreadTask implements Runnable, Delayed {
        private Long millisecond;
        /**
         * 过期时间(单位:ms)
         */
        private Long expTime;

        public DelayThreadTask(Long millisecond) {
            this.expTime = System.currentTimeMillis()+millisecond*1000;
            this.millisecond=millisecond;
        }

        public Long getExpTime() {
            return expTime;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(String.format("我是线程:%s, 延迟时间:%s秒", Thread.currentThread().getName(), millisecond));
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return this.expTime - System.currentTimeMillis();
        }

        @Override
        public int compareTo(Delayed o) {
            return this.expTime.compareTo(((DelayThreadTask)o).getExpTime());
        }
    }
}