java线程池-1

来源:互联网 发布:摄影网络销售技巧 编辑:程序博客网 时间:2024/06/05 18:53

线程池的出现是为了解决在多线程运行环境下程序频繁创建线程而需要较大的系统开销的问题。解决问题的核心就是线程的复用。现在我们看看java在创建线程池的过程中使用了哪些技术。

1.创建方法

        ExecutorService service1 = Executors.newCachedThreadPool();        ExecutorService service2 = Executors.newFixedThreadPool(10);        ExecutorService service3 = Executors.newSingleThreadExecutor();        ExecutorService service4 = Executors.newScheduledThreadPool(10);

可以看到,Executors提供了使用频率最多的四种创建线程池的方式。我们看看它的底层细节。

    public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                      60L, TimeUnit.SECONDS,                                      new SynchronousQueue<Runnable>());    }    public static ExecutorService newFixedThreadPool(int nThreads) {        return new ThreadPoolExecutor(nThreads, nThreads,                                      0L, TimeUnit.MILLISECONDS,                                      new LinkedBlockingQueue<Runnable>());    }    public static ExecutorService newSingleThreadExecutor() {        return new FinalizableDelegatedExecutorService            (new ThreadPoolExecutor(1, 1,                                    0L, TimeUnit.MILLISECONDS,                                    new LinkedBlockingQueue<Runnable>()));    }    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {        return new ScheduledThreadPoolExecutor(corePoolSize);    }    //ScheduledThreadPool的创建过程    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {        return new ScheduledThreadPoolExecutor(corePoolSize);    }    public ScheduledThreadPoolExecutor(int corePoolSize) {        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,              new DelayedWorkQueue());    }    //ScheduledThreadPoolExecutor 继承自 ScheduledThreadPoolExecutor

可以看到四种都使用ThreadPoolExecutor来进行初始化工作。我们继续看看ThreadPoolExecutor的具体内容。

    /**     * Creates a new {@code ThreadPoolExecutor} with the given initial     * parameters and default thread factory and rejected execution handler.     * It may be more convenient to use one of the {@link Executors} factory     * methods instead of this general purpose constructor.     *     * @param corePoolSize the number of threads to keep in the pool, even     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set     * @param maximumPoolSize the maximum number of threads to allow in the     *        pool     * @param keepAliveTime when the number of threads is greater than     *        the core, this is the maximum time that excess idle threads     *        will wait for new tasks before terminating.     * @param unit the time unit for the {@code keepAliveTime} argument     * @param workQueue the queue to use for holding tasks before they are     *        executed.  This queue will hold only the {@code Runnable}     *        tasks submitted by the {@code execute} method.     * @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} is null     */    public ThreadPoolExecutor(int corePoolSize,   //平时允许的线程数量                              int maximumPoolSize,//饱和时最大线程数量                              long keepAliveTime, //无事线程在线程超数后最大存活时间                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue) {  //队列        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,             Executors.defaultThreadFactory(), defaultHandler);    }

从四种线程池的创建可以看出,不同点在于参数内容。1.线程池最大能允许的线程数目,2.超过数目后保存线程的队列类型。在ThreadPoolExecutor里面可以看到一个线程工厂,和一个handler。Executors.defaultThreadFactory()提供的是一个利用runnable实例创建线程的工厂,还记得我们怎么创建线程么。

        Thread thread = new Thread(new Runnable(){            @Override            public void run() {                //do something            }        });

handler的存在是为了处理当机器资源限制时,新提交的线程的处理方法,也就是reject方法。

    private static final RejectedExecutionHandler defaultHandler =        new AbortPolicy();    /**     * A handler for rejected tasks that runs the rejected task     * directly in the calling thread of the {@code execute} method,     * unless the executor has been shut down, in which case the task     * is discarded.     */    public static class CallerRunsPolicy implements RejectedExecutionHandler {        /**         * Creates a {@code CallerRunsPolicy}.         */        public CallerRunsPolicy() { }        /**         * Executes task r in the caller's thread, unless the executor         * has been shut down, in which case the task is discarded.         *         * @param r the runnable task requested to be executed         * @param e the executor attempting to execute this task         */        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {            if (!e.isShutdown()) {                r.run();            }        }    }    /**     * A handler for rejected tasks that throws a     * {@code RejectedExecutionException}.     */    public static class AbortPolicy implements RejectedExecutionHandler {        /**         * Creates an {@code AbortPolicy}.         */        public AbortPolicy() { }        /**         * Always throws RejectedExecutionException.         *         * @param r the runnable task requested to be executed         * @param e the executor attempting to execute this task         * @throws RejectedExecutionException always         */        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {            throw new RejectedExecutionException("Task " + r.toString() +                                                 " rejected from " +                                                 e.toString());        }    }    /**     * A handler for rejected tasks that silently discards the     * rejected task.     */    public static class DiscardPolicy implements RejectedExecutionHandler {        /**         * Creates a {@code DiscardPolicy}.         */        public DiscardPolicy() { }        /**         * Does nothing, which has the effect of discarding task r.         *         * @param r the runnable task requested to be executed         * @param e the executor attempting to execute this task         */        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {        }    }    /**     * A handler for rejected tasks that discards the oldest unhandled     * request and then retries {@code execute}, unless the executor     * is shut down, in which case the task is discarded.     */    public static class DiscardOldestPolicy implements RejectedExecutionHandler {        /**         * Creates a {@code DiscardOldestPolicy} for the given executor.         */        public DiscardOldestPolicy() { }        /**         * Obtains and ignores the next task that the executor         * would otherwise execute, if one is immediately available,         * and then retries execution of task r, unless the executor         * is shut down, in which case task r is instead discarded.         *         * @param r the runnable task requested to be executed         * @param e the executor attempting to execute this task         */        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {            if (!e.isShutdown()) {                e.getQueue().poll();                e.execute(r);            }        }    }

可以看到java线程池的reject的四种策略,一是直接使用当前提交线程处理,二是抛出拒绝异常,三是直接丢弃什么也不做,四是丢弃最老的线程。而java默认选择抛出拒绝异常的方式。

关于线程池中的等待队列,一种SynchronousQueue,一种LinkedBlockingQueue。LinkedBlockingQueue就是用链表连接的线程安全的缓冲队列;SynchronousQueue是一中同步队列,该队列不保存对象,提交的线程被SynchronousQueue同步给相关线程直接执行。在其它地方有看到这样的说法:“SynchronousQueue是这样 一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。不能在同步队列上进行 peek,因为仅在试图要取得元素时,该元素才存在;”

参考内容:
1.jdk1.8源码
2.http://blog.csdn.net/hudashi/article/details/7076814

0 0
原创粉丝点击