Executor并发框架——Executors工厂类

  开发中主要使用Executors提供的工厂方法创建线程池,返回的线程池都实现了ExecutorService接口。Executors还包括ExecutorService、ScheduledExecutorService、Callable 类的工厂和实用方法。下面介绍使用最多的四种创建线程池方法

  Executors.newCachedThreadPool()
  Executors.newFixedThreadPool(int corePoolSize)
  Executors.newScheduledThreadPool(int corePoolSize)
  Executors.newSingleThreadExecutor()

  1.newCachedThreadPool
  创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。cache池线程数支持0-Integer.MAX_VALUE(显然完全没考虑主机的资源承受能力)

    @Test
    public void testCachedThreadPool() throws InterruptedException {
        //线程计数器,每执行完成一条线程,调用countDown()使计数器减1,主线程调用方法await()使其等待,当计数器为0时才被执行
        CountDownLatch latch = new CountDownLatch(10);
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            Thread.sleep(1000);
            cachedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                    // 执行完毕,计数器减1
                    latch.countDown();
                }
            });
        }
        // 主线程等待
        latch.await();
    }

线程名都一样说明线程被回收
这里写图片描述

  2.newFixedThreadPool
  创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  定长线程池的大小最好根据系统资源进行设置。如核心数Runtime.getRuntime().availableProcessors()

    @Test
    public void testFixedThreadPool() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(10);
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            Thread.sleep(1000);
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                    latch.countDown();
                }
            });
        }
        latch.await();
    }

测试发现线程数固定,超出的线程会在队列中等待。
这里写图片描述

  3.newScheduledThreadPool
  创建一个定长线程池,支持定时及周期性任务执行。

    @Test
    public void testScheduledThreadPool() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        //返回ScheduledThreadPoolExecutor对象,实现了ScheduledExecutorService
        ScheduledThreadPoolExecutor scheduledExecutorService = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(10);
        //3秒后执行定时任务
        scheduledExecutorService.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
                latch.countDown();
            }
        },3000, TimeUnit.MILLISECONDS);
        latch.await();
    }

  4.newSingleThreadExecutor
  创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

    @Test
    public void testSingleThreadExecutor() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(10);
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

        for (int i = 0; i <10 ; i++) {
            singleThreadExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                    latch.countDown();
                }
            });
        }
        latch.await();
    }

测试发现线程名都一样,说明为单一线程
这里写图片描述

最近阿里的Java开发规范建议:
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。Executors各个方法的弊端:
1)newFixedThreadPool和newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
2)newCachedThreadPool和newScheduledThreadPool:
主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。

想要熟悉自定义创建ThreadPoolExecutor,可以参考(有例子):
http://blog.csdn.net/qq_23146763/article/details/79181871

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值