多线程之多线程ThreadPoolExecutor

简介

线程是一个程序员一定会涉及到的一个概念,但是线程的创建和切换都是代价比较大的。所以,我们有没有一个好的方案能做到线程的复用呢?这就涉及到一个概念——线程池。合理的使用线程池能够带来3个很明显的好处:
    1.降低资源消耗:通过重用已经创建的线程来降低线程创建和销毁的消耗
    2.提高响应速度:任务到达时不需要等待线程创建就可以立即执行。
    3.提高线程的可管理性:线程池可以统一管理、分配、调优和监控。
    java的线程池支持主要通过ThreadPoolExecutor来实现,我们使用的ExecutorService的各种线程池策略都是基于ThreadPoolExecutor实现的,所以ThreadPoolExecutor十分重要。要弄明白各种线程池策略,必须先弄明白ThreadPoolExecutor。

ThreadPoolExecutor的构造方法

ThreadPoolExecutor有四大构造方法,搞懂参数最多那个,其它的也就理解,具体看APi,
这里只讨论:

ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) 

/**
 * ThreadPoolExecutor有四大构造方法
 * 重点看 七大构造参数的构造方法
 * int corePoolSize,(核心线程池大小,要保持在池中的线程数)
 * 
 * int maximumPoolSize,(线程池中允许的最大线程数)
 * 
 * long keepAliveTime,(线程池中超过corePoolSize数目的空闲线程最大存活时间)
 * 
 * TimeUnit unit,(时间单位)
 * 
 * BlockingQueue<Runnable> workQueue,(阻塞任务队列)
 * 
 * ThreadFactory threadFactory,(新建线程工厂)
 * 
 * RejectedExecutionHandler handler (当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理)
 * @throws IllegalArgumentException if one of the following holds:<br>
 * {@code corePoolSize < 0}<br>
 * {@code keepAliveTime < 0}<br>
 * {@code maximumPoolSize <= 0}<br>
 * {@code maximumPoolSize < corePoolSize}
 * @throws NullPointerException if {@code workQueue}
 * or {@code threadFactory} or {@code handler} is null
 */

想了解BlockingQueue workQueue:
想了解RejectedExecutionHandler handler:http://blog.csdn.net/Kincym/article/details/78318944


public class ThreadPoolExecutorTest {
    private static final CountDownLatch countDownLatch = new CountDownLatch(3);

    public static void main(String[] args) throws InterruptedException {

        ThreadPoolExecutor executorService = (ThreadPoolExecutor) buildPool();
//        countDownLatch.await();

        executorService.shutdown(); //任务执行完毕,关闭线程池。
        executorService.awaitTermination(1,TimeUnit.HOURS);//等待结束,最多等待1个小时,线程池shutdown.
        System.out.println("结束");
    }

    private static ExecutorService buildPool() {
        /**
         * 举例说明:何时启动最大线程数
         * corePoolSize为1,maximumPoolSize为2,workQueue.size()为1
         * I: 当启动2个线程时,corePoolSize启动一个,workQueue里面放一个,maximumPoolSize不启动
         * II: 当启动三个线程时,corePoolSize启动一个,workQueue里面放一个,这时阻塞队列已经满了
         *     这时maximumPoolSize启动了。
         */
        ExecutorService executorService = new ThreadPoolExecutor(1, 2, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1),
                r -> {
                    Thread t = new Thread(r);
                    return t;
                }, new ThreadPoolExecutor.AbortPolicy());

        System.out.println("线程池已创建");
        executorService.execute(() -> sleepSeconds(5));
        executorService.execute(() -> sleepSeconds(5));
        executorService.execute(() -> sleepSeconds(5));
        return executorService;
    }

    private static void sleepSeconds(int seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
            System.out.println("***" + Thread.currentThread().getName() + "***");
//            countDownLatch.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

shutdown():记得一定要关闭线程池。
awaitTermination(long timeout, TimeUnit unit):等待结束,最多等待指定时间。
注意shutdownNow():执行该方法,线程池的状态立刻变成STOP状态,并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务,当然,它会返回那些未执行的任务。它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,如果线程中有sleep 、wait、Condition、定时锁等应用, interrupt()方法是会中断当前的线程(慎用).


在JDKAPI中,更推荐使用Executors工厂类创建线程,前往:http://blog.csdn.net/Kincym/article/details/78306354

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值