array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 并发编程(十三)线程池 - 爱码网

一、线程池的分类

  线程池的创建都是通过Executors(创建者接口)这个接口的方法进行创建的,下面我们来了解一下都有哪些线程池:

  • newFixedThreadPool() : 创建一个固定线程线程池
  • newCachedThreadPool() : 创建一个可扩展的线程池。
  • newScheduledThreadPool() : 创建一个可调度(周期执行)的线程池。
  • newSingleThreadExecutor() : 创建一个单线程化(模拟队列)的线程池。

二、线程池实例分析

newFixedThreadPool【固定线程池】

语法:

//创建一个2个线程的线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(2);
  • 最多2个线程将处于活动状态。
  • 如果提交了两个以上的线程,那么它们将保持在队列中,直到线程可用。
  • 如果一个线程由于执行关闭期间的失败而终止,且执行器尚未被调用,则创建一个新线程。
  • 线程会一直存在,直到池关闭。

实例:

/**
 * 固定线程的线程池
 */
public class TestFixedThreadPool {

    public static void main(final String[] arguments) throws InterruptedException {
        //使用Executors(创建者接口创建一个固定两个线程的线程池)
        ExecutorService executor = Executors.newFixedThreadPool(2);

        //ExecutorService接口转换为线程池实例对象
        ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

        //加入任务前的线程池状态
        System.out.println("线程池大小: " + pool.getCorePoolSize());
        System.out.println("线程池曾经创建过的最大线程数量: " + pool.getLargestPoolSize());
        System.out.println("线程池中允许的最大线程数: " + pool.getMaximumPoolSize());
        System.out.println("线程池中当前线程的数量: " + pool.getPoolSize());
        System.out.println("活动线程数: " + pool.getActiveCount());
        System.out.println("已经分配执行的任务数: " + pool.getTaskCount());

        //线程池中丢进两个线程
        executor.submit(new TestThread());
        executor.submit(new TestThread());

        //加入任务后的线程池状态
        System.out.println("线程池大小: " + pool.getCorePoolSize());
        System.out.println("线程池曾经创建过的最大线程数量: " + pool.getLargestPoolSize());
        System.out.println("线程池中允许的最大线程数: " + pool.getMaximumPoolSize());
        System.out.println("线程池中当前线程的数量: " + pool.getPoolSize());
        System.out.println("活动线程数: " + pool.getActiveCount());
        System.out.println("已经分配执行的任务数: " + pool.getTaskCount());

        //关闭线程池
        executor.shutdown();
    }

    /**
     * 线程实体
     */
    static class TestThread implements Runnable {

        public void run() {
            try {
                Long duration = (long) (Math.random() * 5);//休眠时间,模拟线程内的工作
                System.out.println("运行线程!线程名称为: " + Thread.currentThread().getName());
                TimeUnit.SECONDS.sleep(duration);//休眠
                System.out.println("运行线程完毕!线程名称为: " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果:

并发编程(十三)线程池

newCachedThreadPool【可扩展线程池】

语法:

//创建一个可扩展线程池
ExecutorService executor = Executors.newCachedThreadPool();
  • newCachedThreadPool()方法创建一个具有可扩展线程池的执行器。
  • 核心线程数为零
  • 最大线程数为无限
  • 无任务时,线程存活的最大时间为60s
  • 任务队列为同步移交队列,该队列没有缓冲区,即不会有任务会在该队列中排队,每当有任务要入队时,队列都会将任务移交给一个可用的线程

实例:

/**
 * 可扩展线程池
 */
public class TestCachedThreadPool {

    public static void main(final String[] arguments) throws InterruptedException {
        //使用Executors(创建者接口创建一个可扩展线程池)
        ExecutorService executor = Executors.newCachedThreadPool();

        //ExecutorService接口转换为线程池实例对象
        ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

        //加入任务前的线程池状态
        System.out.println("线程池大小: " + pool.getCorePoolSize());
        System.out.println("线程池曾经创建过的最大线程数量: " + pool.getLargestPoolSize());
        System.out.println("线程池中允许的最大线程数: " + pool.getMaximumPoolSize());
        System.out.println("线程池中当前线程的数量: " + pool.getPoolSize());
        System.out.println("活动线程数: " + pool.getActiveCount());
        System.out.println("已经分配执行的任务数: " + pool.getTaskCount());

        System.out.println("=====开始加入线程=====");
        //线程池中丢进两个线程
        executor.submit(new TestThread());
        executor.submit(new TestThread());
        System.out.println("=====加入线程完毕=====");

        //加入任务后的线程池状态
        System.out.println("线程池大小: " + pool.getCorePoolSize());
        System.out.println("线程池曾经创建过的最大线程数量: " + pool.getLargestPoolSize());
        System.out.println("线程池中允许的最大线程数: " + pool.getMaximumPoolSize());
        System.out.println("线程池中当前线程的数量: " + pool.getPoolSize());
        System.out.println("活动线程数: " + pool.getActiveCount());
        System.out.println("已经分配执行的任务数: " + pool.getTaskCount());

        //关闭线程池
        executor.shutdown();
    }

    /**
     * 线程实体
     */
    static class TestThread implements Runnable {

        public void run() {
            try {
                Long duration = (long) (Math.random() * 5);//休眠时间,模拟线程内的工作
                System.out.println("运行线程!线程名称为: " + Thread.currentThread().getName());
                TimeUnit.SECONDS.sleep(duration);//休眠
                System.out.println("运行线程完毕!线程名称为: " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果:

并发编程(十三)线程池

newScheduledThreadPool【可调度(周期执行)线程池】

//创建一个大小为2的可调度(周期执行)的线程池
ExecutorService executor = Executors.newScheduledThreadPool(2);

实例: 

/**
 * 创建一个可调度(周期运行)的线程池。
 * 此线程池支持定时以及周期性执行任务的需求。
 */
public class TestScheduledThreadPool {

    public static void main(String[] args) {
        //使用Executors(创建者接口创建一个可调度的线程池)
        ScheduledExecutorService service = Executors.newScheduledThreadPool(2);


        System.out.println("=====观察周期线程实体(过了周期时间需检测上一个任务,执行完毕后才会接着执行)=====开始");
        scheduleAtFixedRate(service, 1000);//由于执行时间在周期间隔内,每隔5秒会执行一次
        scheduleAtFixedRate(service, 6000);//由于执行时间在周期间隔外,需等上一个任务执行完了以后才能继续执行,所以每隔6秒会执行一次
        System.out.println("=====观察周期线程实体(过了周期时间需检测上一个任务,执行完毕后才会接着执行)=====结束");

        System.out.println("=====观察周期线程实体(从上一个任务结束时间开始计时,过了周期时间立即执行下一个任务)=====开始");
        scheduleWithFixedDelay(service, 1000);//周期为5秒,从任务结束开始计算周期,实际每个任务执行的间隔为5+1=6秒
        scheduleWithFixedDelay(service, 6000);//周期为5秒,从任务结束开始计算周期,实际每个任务执行的间隔为5+6=11秒
        System.out.println("=====观察周期线程实体(从上一个任务结束时间开始计时,过了周期时间立即执行下一个任务)=====开始");


    }

    /**
     * 周期线程实体(过了周期时间需检测上一个任务,执行完毕后才会接着执行)
     * <p>
     * 执行步骤
     * 1、是以上一个任务开始的时间计时
     * 2、period时间过去后,检测上一个任务是否执行完毕,如果上一个任务执行完毕,则当前任务立即执行
     * 3、如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行
     */
    private static void scheduleAtFixedRate(ScheduledExecutorService service, final int sleepTime) {
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                long start = new Date().getTime();
                System.out.println("scheduleAtFixedRate 开始执行时间:" + DateFormat.getTimeInstance().format(new Date()));
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                long end = new Date().getTime();
                System.out.println("scheduleAtFixedRate 执行花费时间=" + (end - start) / 1000 + "m");
                System.out.println("scheduleAtFixedRate 执行完成时间:" + DateFormat.getTimeInstance().format(new Date()));
                System.out.println("======================================");
            }
        }, 1000, 5000, TimeUnit.MILLISECONDS);
    }

    /**
     * 周期线程实体(从上一个任务结束时间开始计时,过了周期时间立即执行下一个任务)
     * <p>
     * 执行步骤
     * 1、是以上一个任务结束的时间计时
     * 2、period时间过去后,立即执行。
     */
    private static void scheduleWithFixedDelay(ScheduledExecutorService service, final int sleepTime) {
        service.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                long start = new Date().getTime();
                System.out.println("scheduleWithFixedDelay 开始执行时间:" + DateFormat.getTimeInstance().format(new Date()));
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                long end = new Date().getTime();
                System.out.println("scheduleWithFixedDelay执行花费时间=" + (end - start) / 1000 + "m");
                System.out.println("scheduleWithFixedDelay执行完成时间:" + DateFormat.getTimeInstance().format(new Date()));
                System.out.println("======================================");
            }
        }, 1000, 5000, TimeUnit.MILLISECONDS);
    }
}

newSingleThreadExecutor【单线程化(模拟队列)线程池】

语法:

//创建一个单线程化(模拟队列)的线程池
ExecutorService executor = Executors.newSingleThreadExecutor();
  • newSingleThreadExecutor()方法创建一次执行单个任务的执行程序。
  • 此线程池保证所有任务的执行顺序按照任务的提交顺序执行

实例:

/**
 * 单例/线程化线程池【类似模拟一个队列去处理】
 */
public class TestSingleThreadPool {

    public static void main(String[] args) {
        //使用Executors(创建者接口创建一个单例/线程化线程池)
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

        for (int i = 0; i < 10; i++) {
            String threadName = "我是序号为:" + (i + 1) + "的线程";
            singleThreadExecutor.execute(new TestThread(threadName));
        }
        singleThreadExecutor.shutdown();
        System.out.println("main方法执行完毕,线程还在异步运行");

    }

    /**
     * 线程实体
     */
    static class TestThread implements Runnable {
        private String threadName;

        public TestThread(String threadName) {
            this.threadName = threadName;
        }

        public void run() {
            try {
                System.out.println("运行线程!线程名称为: " + threadName);
                TimeUnit.SECONDS.sleep(3);//线程休眠3秒,模拟线程中处理的业务
                System.out.println("运行线程完毕!线程名称为: " + threadName);
                System.out.println("========华丽的分割线========");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

运行结果:

并发编程(十三)线程池

 

参考资料:

相关文章: