如何优化 ThreadPoolExecutor

一、想让线程池在初始化时就干活,而不是等到第一次提交任务时才创建线程,该怎么做?

    /**
     * Starts all core threads, causing them to idly wait for work. This
     * overrides the default policy of starting core threads only when
     * new tasks are executed.
     *
     * @return the number of threads started
     */
    public int prestartAllCoreThreads() {
        int n = 0;
        while (addWorker(null, true))
            ++n;
        return n;
    } 

 

 

二、tomcat 8 如何优化ThreadPoolExecutor

  1.  tomcat优化:ThreadPoolExecutor#execute 在抛出 RejectedExecutionException时, 仍然尝试给队列添加任务

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the <tt>Executor</tt> implementation.
     * If no threads are available, it will be added to the work queue.
     * If the work queue is full, the system will wait for the specified
     * time and it throw a RejectedExecutionException if the queue is still
     * full after that.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution - the queue is full
     * @throws NullPointerException if command or unit is null
     */
    public void execute(Runnable command, long timeout, TimeUnit unit) {
        submittedCount.incrementAndGet();
        try {
            super.execute(command);
        } catch (RejectedExecutionException rx) {
            if (super.getQueue() instanceof TaskQueue) {
                final TaskQueue queue = (TaskQueue)super.getQueue();
                try {
                    if (!queue.force(command, timeout, unit)) {
                        submittedCount.decrementAndGet();
                        throw new RejectedExecutionException("Queue capacity is full.");
                    }
                } catch (InterruptedException x) {
                    submittedCount.decrementAndGet();
                    throw new RejectedExecutionException(x);
                }
            } else {
                submittedCount.decrementAndGet();
                throw rx;
            }

        }
    }

 

  2. TaskQueue 继承 LinkedBlockingQueue, 重写了offer方法

也可以分析下tomcat线程池在防止内存溢出方面做的工作

tomcat的ThreadExecutor其中一个重要的作用,就是对线程的ThreadLocal缓存的变量进行清理;(待验证)

为什么ThreadLocal要进行清理呢?如果是一个简单的main函数的话,那么在这个主线程中使用ThreadLocal缓存在程序结束之后,自动就随着JVM退出而消亡了;

如果是开启的一个线程,这个线程中使用了ThreadLocal缓存,线程退出,这种情况这块内存仍旧会进行回收;但是,线程池的线程是重复利用的,

很有可能会在某处使用了ThreadLocal缓存,但是忘记remove掉了,这种在线程池中是很致命的

 

posted @ 2019-01-28 10:40 等风来。。 Views(...) Comments(...) Edit 收藏
------------------------------------------------------------------------------------------------------------ --------------- 欢迎联系 x.guan.ling@gmail.com--------------- ------------------------------------------------------------------------------------------------------------