线程池

线程池

        在Java多线程中,如果并发的线程数量过大,并且每一个线程都是执行了一个很短的任务就结束了,这样频繁的创建销毁线程会极大的降低系统的效率。所以在Java中引入 了线程池使得线程可以得到复用。既执行完一个任务不会被销毁而去执行下一个任务。

以下基于jdk1.7.8.1源码来进行分析

目录

线程池

线程池的继承关系

线程池的基本属性

线程池的构造函数

线程池的执行流程

线程池的终止

Submit方法与Collable、Future


线程池的继承关系

          

Excutor接口:

public interface Executor {

    /**
     * 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.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution.
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

它只有一个执行方法execute();

ExecutorService接口:

它提供了将任务交给执行者的方法(submit())、关闭(shutDown())...

AbstractExecutorService类:

一个抽象类主要是实现了ExecutorService接口的方法。

ThreadPoolExecutor类 :

实现线程池最主要的类。

 

线程池的基本属性

 //线程池的状态
    volatile int runState;
    static final int RUNNING    = 0;//运行状态
    static final int SHUTDOWN   = 1;
    static final int STOP       = 2;
    static final int TERMINATED = 3;

    private final BlockingQueue<Runnable> workQueue;//缓存队列

     //互斥锁
    private final ReentrantLock mainLock = new ReentrantLock();

     //终止条件
    private final Condition termination = mainLock.newCondition();

     //存放线程的工作集
    private final HashSet<Worker> workers = new HashSet<Worker>();

    private volatile long  keepAliveTime;//空闲时间

     //表示是否允许线程在空闲状态仍能存活
    private volatile boolean allowCoreThreadTimeOut;

    private volatile int   corePoolSize;//核心池大小

    private volatile int   maximumPoolSize;//最大池大小

    private volatile int   poolSize;//当前大小

     /**
	  *表示当拒绝处理任务时的策略,有以下四种取值
		ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 
		ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 
		ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
		ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 
	  */
    private volatile RejectedExecutionHandler handler;

    private volatile ThreadFactory threadFactory;//线程工厂

    private int largestPoolSize;//记录之前线程最大时的大小

    private long completedTaskCount;

corePoolSize:核心池的大小。默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达 的任务放到缓存队列中。

maximumPoolSize:线程池最大线程数。表示在线程池中最多能创建多少个线程。

keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程数大于corePoolSize时,keepAliveTime         才会起作用,直到线程池中的线程数不大于corePoolSize。,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时          间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut()方              法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;

unit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:

        

WorkQueue:阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,要对线程池的运行过程产生重大影响。

  1. ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小。
  2. LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_Vlaue
  3. SynchronousQueue:这个队列比较特殊,它不会保存提交的任务 ,而是直接创建了一个线程去执行新来的任务

threadFactory:线程工厂,用来创建线程

Hander:表示当拒绝处理任务时的策略,有以下四种取值

        ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

        

public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an <tt>AbortPolicy</tt>.
         */
        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();
        }
    }

        ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。

        

 public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a <tt>DiscardPolicy</tt>.
         */
        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) {
        }
    }

        ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

       

public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a <tt>DiscardOldestPolicy</tt> 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);
            }
        }
    }

        ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

 public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a <tt>CallerRunsPolicy</tt>.
         */
        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();
            }
        }
    }

 

线程池的构造函数

     构造函数——1

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

第一个构造函数,调用了最后一个构造函数。它调用了默认的线程工厂和默认的拒绝策略

static class DefaultThreadFactory implements ThreadFactory {
        static final AtomicInteger poolNumber = new AtomicInteger(1);
        final ThreadGroup group;
        final AtomicInteger threadNumber = new AtomicInteger(1);
        final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null)? s.getThreadGroup() :
                                 Thread.currentThread().getThreadGroup();
			//设置线程名字
			namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
        //创建一个线程
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
		//设置为非守护线程
            if (t.isDaemon())
                t.setDaemon(false);
			//设置线程优先级
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

这是默认的线程工厂,里面设置了线程的名字,设置线程为非守护线程,设置优先级为Thread.NORM_PRIORITY

构造函数——2

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

调用了最后一个构造函数。它使用了默认的拒绝策略

构造函数——3

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

调用了最后一个构造函数。它使用了默认的线程工厂

构造函数——4

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        //进行了参数检测
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

最终实现的构造函数,进行了对参数的检测处理。如果核心池大小小于0或者最大池大小小于等于0或者核心池大小大于最大池大小或者空闲等待时间小于0 就抛出IllegalArgumentException异常。如果阻塞队列为null或者线程工厂为null或者拒绝策略为null就抛出NullPointerException异常。

线程池的执行流程

 public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
            if (runState == RUNNING && workQueue.offer(command)) {
                if (runState != RUNNING || poolSize == 0)
                    ensureQueuedTaskHandled(command);
            }
            else if (!addIfUnderMaximumPoolSize(command))
                reject(command); // is shutdown or saturated
        }
    }

线程池的终止

Shutdown()和shutdownNow()两个方法,用于线程池的关闭。

Shutdown():不会立即终止线程池,而是要等待所有的任务缓存队列中的任务都执行完才终止,但也不会接受新的任务

shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务

public void shutdown() {

	SecurityManager security = System.getSecurityManager();
	if (security != null)
            security.checkPermission(shutdownPerm);

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (security != null) { // Check if caller can modify our threads
                for (Worker w : workers)
                    security.checkAccess(w.thread);
            }

            int state = runState;
			//线程状态改变
            if (state < SHUTDOWN)
                runState = SHUTDOWN;
			
            try {
                for (Worker w : workers) {
                    w.interruptIfIdle();//终止任务
                }
            } catch (SecurityException se) { // Try to back out
                runState = state;
                // tryTerminate() here would be a no-op
                throw se;
            }
            //尝试终止线程池
            tryTerminate(); // Terminate now if pool and queue empty
        } finally {
            mainLock.unlock();
        }
    }
public List<Runnable> shutdownNow() {
        /*
         * shutdownNow differs from shutdown only in that
         * 1. runState is set to STOP,
         * 2. all worker threads are interrupted, not just the idle ones, and
         * 3. the queue is drained and returned.
         */
	SecurityManager security = System.getSecurityManager();
	if (security != null)
            security.checkPermission(shutdownPerm);

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (security != null) { // Check if caller can modify our threads
                for (Worker w : workers)
                    security.checkAccess(w.thread);
            }

            int state = runState;
            if (state < STOP)
                runState = STOP;

            try {
                for (Worker w : workers) {
                //终止任务
                    w.interruptNow();
                }
            } catch (SecurityException se) { // Try to back out
                runState = state;
                // tryTerminate() here would be a no-op
                throw se;
            }

            List<Runnable> tasks = drainQueue();
                //尝试终止线程池
            tryTerminate(); // Terminate now if pool and queue empty
            return tasks;
        } finally {
            mainLock.unlock();
        }
    }

 private void tryTerminate() {
        if (poolSize == 0) {
            int state = runState;
            if (state < STOP && !workQueue.isEmpty()) {
                state = RUNNING; // disable termination check below
                addThread(null);
            }
            if (state == STOP || state == SHUTDOWN) {
				//将线程状态设为TERMINATED
                runState = TERMINATED;
				//发送信号关闭线程池
                termination.signalAll();
                terminated();
            }
        }
    }

Submit方法与Collable、Future

public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Object> ftask = newTaskFor(task, null);
       //调用了execute()方法
        execute(ftask);
        return ftask;
        //返回一个Future对象
    }
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

Callable也是实现多线程的一种办法。

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

它的call方法相当于Runnable的run方法。但是不同的是call方法可以抛出异常。Callable的任务执行后可返回值,而Runnable的任务是不能返回值(是void)。运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它可以返回正在执行的任务,可以终止任务。

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值