Executors

1. 介绍

线程池工厂,在实际生产环境中,线程的数量必须得到控制,盲目的大量创建线程对系统性能是有伤害的。

2. 主要方法

2.1 newFixedThreadPool()

​ 该方法返回一个固定线程数量的线程池,该线程池中的线程数量始终不变,当有一个新的任务提交时,线程池中若有空闲线程,则立即执行,若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。

线程数固定,队列无限大

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

示例:

/**
 * newFixedThreadPool
 * 若任务生产的速度远远大于任务处理的速度,阻塞队列的容量就会一直变大,有可能产生内存溢出
 */
public class Test01 {

    @Test
    public void test01() throws Exception{
        ExecutorService es = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 30; i++) {
            es.execute(() -> {
                System.out.println(Instant.now().getEpochSecond() + " " + Thread.currentThread().getId());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        Thread.sleep(13000);
    }

}

2.2 newSingleThreadExecutor()

​ 该方法返回一个只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务。

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

2.3 newCachedThreadPool()

​ 该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。

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

2.4 newSingleThreadScheduledExecutor()

​ 该方法返回一个ScheduledExecutorService对象,线程池大小为1。ScheduledExecutorService接口在ExecutorService接口之上扩展了在给定时间执行某任务的功能,如在某个固定的延时之后执行,或者周期性执行某个任务。

    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }

2.5 newScheduledThreadPool()

​ 该方法也返回一个ScheduledExecutorService对象,但该线程池可以指定线程数量。

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

主要有三种用法,实例:

    /**
     * schedule, 在给定的时间,对任务进行一次调度
     *
     * @throws Exception
     */
    @Test
    public void test01() throws Exception {
        ScheduledExecutorService es = Executors.newScheduledThreadPool(3);

        for (int i = 0; i < 10; i++) {
            es.schedule(() -> {
                System.out.println("run start " + Thread.currentThread().getId());
            }, 2, TimeUnit.SECONDS);
        }
        Thread.sleep(10000);
    }


    /**
     * scheduleAtFixedRate 以任务开始为时间起点,然后每个period周期执行一次任务,
     * 如果执行任务时间超过了周期时间,则任务完成后立即开启下一次任务
     *
     * 下面例子实际周期变成了5
     *
     * @throws Exception
     */
    @Test
    public void test02() throws Exception {
        ScheduledExecutorService es = Executors.newScheduledThreadPool(3);

        for (int i = 0; i < 1; i++) {
            es.scheduleAtFixedRate(() -> {
                System.out.println("run start " + Instant.now().getEpochSecond() + " " + Thread.currentThread().getId());
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, 2, 3, TimeUnit.SECONDS);
        }
        Thread.sleep(20000);
    }


    /**
     * scheduleWithFixedDelay 以上一个任务结束后为开始计时,delay时间后,下一个线程执行
     *
     * 下面例子实际周期变成了8
     * @throws Exception
     */
    @Test
    public void test03() throws Exception {
        ScheduledExecutorService es = Executors.newScheduledThreadPool(3);

        for (int i = 0; i < 1; i++) {
            es.scheduleWithFixedDelay(() -> {
                System.out.println("run start " + Instant.now().getEpochSecond() + " " + Thread.currentThread().getId());
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, 2, 3, TimeUnit.SECONDS);
        }
        Thread.sleep(20000);
    }

发布了311 篇原创文章 · 获赞 114 · 访问量 39万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章