线程池源码

版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在页面明显位置给出原文链接。 https://blog.csdn.net/mengxiangqihangz/article/details/82991256

了解线程池之前先了解一个类:

Executors类:这是一个工厂类。里面包含了创建线程池的各种方法

  • newFixedThreadPool(int nThreads)方法:创建指定线程数的线程池
new newFixedThreadPool(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),new DefaultThreadFactory(),new AbortPolicy())

实际创建的是一个 核心线程数:n,最大线程数:n。线程超时时间:0。阻塞队列:LinkedBlockingQueue,最大值为Integer.MAX_VALUE。DefaultThreadFactory:默认的创建线程的工厂。AbortPolicy:当阻塞队列已满时的拒绝策略,默认的策略为抛出异常,可以自己去实现,如改为线程sleep,但是意义不大,因为阻塞队列太大,阻塞队列还没满,就已经内存溢出了。

  • newSingleThreadExecutor()方法:创建单个线程的线程池

new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),new DefaultThreadFactory(),new AbortPolicy())

实际创建的是一个 核心线程数:1,最大线程数:1。线程超时时间:0。阻塞队列:LinkedBlockingQueue,最大值为Integer.MAX_VALUE 

  • newCachedThreadPool()方法:创建带缓存的线程池
new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<Runnable>(),new DefaultThreadFactory(),new AbortPolicy()) 

实际创建的是一个 核心线程数:0,最大线程数:int最大值,线程超时时间:60,TimeUnit.SECONDS:表示存活时间的单位,可以转化成各种时间。阻塞队列:SynchronousQueue

线程池是什么,线程池是怎么工作的?

 很多初学者,包括当初的我,都曾经被各种误导,一直以为线程池中运行的线程就是我们excute的线程。

线程池里面运行的是一定数量的线程,但是这些线程不是我们通过pool.excute(Runnable thread),提交的的线程对象(excute的入参传Runnable的对象更节省空间,而不是Thread的对象)。而是通过创建线程池时,传入的线程创建工厂(DefaultThreadFactory)创建的。而通过excute提交的只是一个普通的java对象,一个实现了Runnable的类对象。线程池中对于我们的实现类中方法的调用,只是普通的run()方法调用。实际上可以把excute的对象当成一个task,task中的内容就是run()方法中的内容。

那么线程池处理的实际任务,就是我们excute的一堆Runnable对象,调用各自的run方法的过程。

测试代码:

		Thread thread = new Thread(){
			@Override
			public void start(){
				setName("自己命名的线程");
				System.out.println("start");
				super.start();
			}
			@Override
			public void run(){
				for (int i = 0	; i < 10; i++) {
					try {
						Thread.currentThread().sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				System.out.println("over!");
			}
		};
		
		thread.start();
		
//		ExecutorService executor = Executors.newFixedThreadPool(2);
//		executor.execute(thread);
		
		ThreadGroup group = Thread.currentThread().getThreadGroup();
		Thread[] threads = new Thread[group.activeCount()];
		int num = group.enumerate(threads);
		for (int i = 0; i < threads.length; i++) {
			System.out.println(threads[i].getName());
		}

如果是线程直接调用start启动,则打印了"running start",而且线程的名字指定了。

如果是线程池启动,没有调用实现的start方法,而且线程的名字并非我们指定的线程名称。

其实通过excute(Runnable),传入的是Runnable类型,就能够发现这些问题,只是初学的时候,思考的不够仔细。

ThreadPoolExecutor 源码

设计思路:

铺垫

  1. 线程池的初始化 
     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;//拒绝策略。当线程池中的线程等于最大线程数,且任务队列已满,此时提交任务的处理策略,默认为抛出异常。
        }
    
    }
  2. 一个变量,记录两个值
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));//线程安全的原子数据操作
    ctl的高3位记录的是线程池的运行状态,低29位记录的是线程池中的线程数。
    原理
        private static final int COUNT_BITS = Integer.SIZE - 3;//29
        private static final int CAPACITY   = (1 << COUNT_BITS) - 1;//容量  低29位存储 011111111111111111111111111111
        private static final int RUNNING    = -1 << COUNT_BITS; //11100000000000000000000000000000
        private static final int SHUTDOWN   =  0 << COUNT_BITS;	//00000000000000000000000000000000
        private static final int STOP       =  1 << COUNT_BITS; //00100000000000000000000000000000
        private static final int TIDYING    =  2 << COUNT_BITS; //01000000000000000000000000000000
        private static final int TERMINATED =  3 << COUNT_BITS; //01100000000000000000000000000000
    
        private static int runStateOf(int c)     { return c & ~CAPACITY; }//  取c的高3位
        private static int workerCountOf(int c)  { return c & CAPACITY; }// 线程池的线程数,与capacity进行与操作,取低 29位k,capacity 全是1,所以是与。
        private static int ctlOf(int rs, int wc) { return rs | wc; } //合并,rs是带后面0的,wc是带前面0的,进行或运行。
        
    
  3. 一些属性

    一些核心属性
        private volatile boolean allowCoreThreadTimeOut;//为true时,线程数小于核心线程数,keepAliveTime依然有效。
        private volatile int corePoolSize;//核心线程数
        private volatile int maximumPoolSize;//最大线程数
        private final BlockingQueue<Runnable> workQueue;//任务队列,用于保存等待执行的任务的阻塞队列
        private volatile long keepAliveTime;//当线程数大于核心线程数是起作用
        private volatile ThreadFactory threadFactory;//线程创建工厂
        private volatile RejectedExecutionHandler handler;//拒绝策略
        private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();//默认拒绝策略,为抛出异常
        private final ReentrantLock mainLock = new ReentrantLock();//对象锁
    
        private final HashSet<Worker> workers = new HashSet<Worker>();//用来存储待执行的任务,任务被封装成了Worker对象
    
        private final Condition termination = mainLock.newCondition();//Condition 的实例,用于 termination.await()   相当与线程的 wait()
        //    	termination.signalAll(); //相当与线程的  notifyAll()
    

新增任务流程

excute方法

 public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         * 分3步
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         *	当正在运行的线程小于 核心线程数,新建线程。

         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *	当 
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {//当新建线程小于核心线程数时。
            if (addWorker(command, true))//这里会在addWorker里面详细说明,
                    //主要逻辑就是,如果新增线程成功,则返回。否则重新判断线程池运行状态,将任务添加到任务队列中
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {//如果线程池依然是运行状态,添加任务到任务队列成功
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }

addWorker方法

/**
*    首先明白这个方法是做什么的。 这个方法是新建线程的 方法。
*/
private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null &&! workQueue.isEmpty()))//
                return false;

            for (;;) {//重点
                int wc = workerCountOf(c);
                if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;//如果线程数大于线程池容量(固定的),或者core为true时,大于核心线程数,core为false时大于最大线程数,都不创建新线程。
                if (compareAndIncrementWorkerCount(c))//并发就是在这里控制的。如果ctl等于期望值c,则 ctl+1。也就是并发的多条线程执行到此处,需要一条一条通过。每次循环只能有一条线程通过。其它的线程都需要重新进入循环,重新判断。
//简单的两种情况:一种 线程数远小于核心线程数,则返回的线程将在下一次循环时,通过。
                另一种 线程数只比核心线程数 小1,则循环的线程,都将在 wc >= corePoolSize 时返回false。对于这条任务 excute的第一层判断 addWork之后返回false,表示新增线程失败。此任务需要添加到队列中。
//private boolean compareAndIncrementWorkerCount(int expect) {//利用cas算法,+1
//        return ctl.compareAndSet(expect, expect + 1);
//    }
                    break retry;
                c = ctl.get();  // Re-read ctl,重新获取clt
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            final ReentrantLock mainLock = this.mainLock;
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int c = ctl.get();
                    int rs = runStateOf(c);

                    if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

猜你喜欢

转载自blog.csdn.net/mengxiangqihangz/article/details/82991256