Executors线程池

/**
 * Executors的好处:可创建固定数量线程的线程池,并可以重用线程池中的线程,减少创建对象, 销毁对象,节省资源
 * 并且支持线程定时,中断操作,可控制并发的线程数量
 * 而new Thread,在调用run方法后,如果里面的任务执行完毕, 则这个线程会自动关闭了,如果下次还想用
 * 则需要再次new Thread,重新创建, 不断创建的话, 会占用较多的资源,可能会造成oom,而且 每个线程不易于统一管理

 execute和submit比较
 * execute 执行不需要返回值的任务
 * submit 执行需要返回值的, 返回Future 对象,通过Future 的get方法获返回值,当调用get方法时,当前线程阻塞,直到任务完成
 *
 * 执行execute时,是在ThreadPoolExecutor这个类中,主要分为三步
 * 1.先判断当前线程数量是否大于核心线程数,如果小于,则创建线程开始执行任务,如果大于则进入BlockingQueue<Runnable> 队列 排队
 * 2.进入排队后,再次进行检查状态(因为有些线程步骤1检查后就死了,或者线程池关闭了),线程池若没有线程则创建新的线程, 线程池关闭,则回滚入队列
 * 3.如果队列满了, 无法进入队列,就尝试开启新的线程, 则判断如果线程池线程满了,也就是达到最大线程数,这时候就执行拒绝策略,
 *      如果开启新的线程成功,则就入新队列
  * 而在执行execute的三步中,最主要的方法就是addWorker----worker----getTask
 *
 *  new Thread().start()在一旦执行起来之后,只有在执行完毕后才线程才进入stop状态,不能再次start,如果想在重新复用,只能在
 *  runnable中下手,可以用死循环一直执行runnable.run的方法,在run的时候检查是否有新的任务进来, 有新任务,就执行新任务的run方法,
 *  如果有多个新任务, 就把多个任务的run串联起来,一个个的去执行,没有新任务的时候,就进入队列阻塞,
 *  Executors真正的最底层核心 就是这个
 */
public class ThreadPoolUtils {
    private ScheduledExecutorService scheduledExecutorService;
    private ExecutorService fixedThreadPool;

    /*--------------------------定时线程------------------------------------------------------------------*/
    /**
     * 开启固定数量线程的线程池
     * 也支持开启定时的线程池
     * 这里就传 1, 模拟只支持一个线程的线程池
     * @param runnable
     * @param start 开始几秒后执行第一次
     * @param delay 第一次之后,每次间隔时间delay后,执行下一次
     *              默认使用秒
     */
    public void startTimerPool(Runnable runnable,long start,long delay){
        scheduledExecutorService = Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleWithFixedDelay(runnable,start,delay, TimeUnit.SECONDS);
    }

    /**
     * 关闭定时的线程池
     */
    public void stopTimerPool(){
        scheduledExecutorService.shutdown();
        scheduledExecutorService = null;
    }

/*------------------------------------缓存线程,尽量少用--------------------------------------------------------*/

    /**
     * 创建缓存线程池,如果第一个线程任务完成, 则第二个线程会复用第一个线程,不会开启新线程,若第一个没完成,则第二个开启新线程去做
     * 超过60s没用的线程 会默认销毁
     * 适用于大流量但是周期短的异步处理
     *
     * 容易出现OOM,因为线程量大,每个线程占用内容多,就会出现oom
     * 1w个线程,每个线程占1M,这就是10G,但是电脑是8G的,就oom了
     *
     * 这种线程池 能少用就少用
     */
    public void startCachePool(Runnable... runnables){
        if (null == runnables)return;
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i=0;i<runnables.length;i++){
            executorService.execute(runnables[i]);
        }
    }

/*------------------------------------固定线程数量的线程池---------------------------------------------------*/
    /**
     * 创建定长的线程数的线程池,线程数量可控制的并发
     * 超过规定的并发量 就排队等着
     * 和CachedThreadPool不同,她的线程不会自动销毁
     *
     * @param poolSize 线程的数量
     */
    public void startFixedPool(int poolSize,Runnable... runnable){
         fixedThreadPool = Executors.newFixedThreadPool(poolSize);
        for (int i = 0;i<runnable.length;i++){
            fixedThreadPool.execute(runnable[i]);
        }
    }

    /**
     * 关闭线程池
     */
    public void stopFixedPool(){
        if (null == fixedThreadPool)return;
        fixedThreadPool.shutdown();
        fixedThreadPool = null;
    }

    /*------------------------------------单一线程数量的线程池---------------------------------------------------*/

    /**
     * 创建唯一的线程来执行,任务顺序执行,一个执行完后执行下一个
     * @param runnable
     */
    public void startSinglePool(Runnable runnable){
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(runnable);
    }
}

 

转载于:https://my.oschina.net/fbf8866/blog/3079329

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值