ThreadPoolExecutor源码1
参考:https://www.cnblogs.com/liuyun1995/p/9305273.html
ThreadPoolExecutor1 executorService1 = new ThreadPoolExecutor1(3)
线程池的线程是懒初始化的,第一个任务来了创建一下执行,执行完了等待队列,只会从队列拿任务,不会直接接受任务。第二个任务来了,不会加到队列,也不会给第一个线程去执行,而是创建一个线程执行,第二个线程执行完了等待队列。第三个任务来了,即使前面2个线程执行完了,也不会给前面2个线程执行,而是创建第三个线程去执行,执行完了就等队列。第四个任务来了,不会直接给线程去执行,而是加到队列,让前3个线程去队列取任务。
Worker里面封装了这个任务,并且里面有一个线程池的线程,总共3个Worker,3个任务(3个第一个任务),3个线程。线程run时候就开一个线程去执行Worker里的第一个任务,线程Thread run的时候,是开一个线程池的线程,然后Thread里面的Runnable的run方法在这个线程里面执行,所以Worker要设置成这个Thread的Runnable,就是Worker的run方法在这个线程里面执行(转调外部类的runWorker方法,把worker传进去)runWorker方法就在这个线程里面执行。Worker里面仅仅保存的是这个worker的第一个任务,第一个任务执行完会死循环执行queue队列的任务。
Worker是作为一个Runnable存在于线程池的线程Thread中的,所有Worker的方法都在这个线程中执行(多个线程执行Worker类的相同方法)。runWorker执行的时候,worker w成为了这个线程的局部变量,w.lock();w.unlock(); 多线程执行同一个方法不要紧,只要不是使用共享变量就没事。由于w不是共享变量,一个线程一个局部变量w,所以不会抢锁。一个线程的Worler w不会跑到另一个线程里面去,所以是单线程访问的。
executorService.execute(new Runnable() {} = firstTask); Worker w = new Worker(firstTask); Worker(Runnable firstTask) { setState(-1); this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); }
一个线程池线程中一个Runnable(Worker),这个Runnable(Worker)不仅仅执行第一个任务还执行队列的任务,这个Runnable一直不会退出。
所有的任务都在这个线程里面执行,所有的任务都由这个worker执行。
要想w.lock();w.unlock();有线程抢锁,那么一个worker就要被设置到多个线程池的线程去,一个Worker成为多个线程的Runnable,多个线程同时执行时候,这一个Runnable在多个线程中执行,成为多个线程的局部变量w,w.lock();w.unlock();就会出现多线程抢锁。但是不行,
线程跟worker是一对一的关系,通过Runnable建立起来的。
其他线程调用中断interrupt相关方法时候,会从workers中获取一个worker,此时worker w就存在于另一个线程中了,就会多个线程使用这个worker w了。此时锁就有意义了。
Worker初始化时候,只会在一个线程池的线程中,是单线程。但是其他线程可以从workers里面获取这个worker,就是多线程访问。
线程池的所有线程全保存在workers里面的worker里面的thread上面。
超过3个任务进来, 不会创建线程,而是直接丢到队列里面去,然后流程执行完。
Worker继承AQS也就是一个ReentantLock,不同的线程调用worker w的lock和unlock方法可以实现锁的功能,不同的线程可以锁住不同的代码段。
当一个任务提交至线程池之后,
1. 线程池首先判断核心线程池里的线程是否已经满了。如果不是,则创建一个新的工作线程来执行任务。否则进入2.
2. 判断工作队列是否已经满了,倘若还没有满,将线程放入工作队列。否则进入3.
3. 判断线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行。如果线程池满了,则交给饱和策略来处理任务。
RUNNING:111 SHUTDOWN:000 STOP:001 TIDYING:010 TERMINATED:011
SHUTDOWN = 0,STOP|TIDYING|TERMINATED > 0,RUNNING < 0
新建一个线程池时它的状态为Running,这时它不断的从外部接收并处理任务,当处理不过来时它会把任务放到任务队列中;
之后我们可能会调用shutdown()来终止线程池,这时线程池的状态从Running转为Shutdown,它开始拒绝接收从外部传过来的任务,但是会继续处理完任务队列中的任务;
我们也可能调用shutdownNow()来立刻停止线程池,这时线程池的状态从Running转为Stop,然后它会快速排空任务队列中的任务并转到Tidying状态,处于该状态的线程池需要执行terminated()来做相关的扫尾工作,
执行完terminated()之后线程池就转为Terminated状态,表示线程池已终止。这些状态的转换图如下所示。
- RUNNING:接受新任务并且处理阻塞队列里的任务
- SHUTDOWN:拒绝新任务但是处理阻塞队列里的任务
- STOP:拒绝新任务并且抛弃阻塞队列里的任务同时会中断正在处理的任务
- TIDYING:所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为0,将要调用terminated方法
- TERMINATED:终止状态。terminated方法调用完成以后的状态
线程池状态转换
RUNNING -> SHUTDOWN
显式调用shutdown()方法, 或者隐式调用了finalize()方法
(RUNNING or SHUTDOWN) -> STOP
显式调用shutdownNow()方法
SHUTDOWN -> TIDYING
当线程池和任务队列都为空的时候
STOP -> TIDYING
当线程池为空的时候
TIDYING -> TERMINATED
当 terminated() hook 方法执行完成时候
corePoolSize:corePoolSize –> workQueue –> maximumPoolSize。如果运行的线程少于 corePoolSize,则创建新线程来处理任务,即使线程池中的其他线程是空闲的;当线程池中的线程数量大于等于 corePoolSize 且小于 maximumPoolSize,则只有当workQueue满时才创建新的线程去处理任务;当运行的线程数量大于等于maximumPoolSize,这时如果workQueue已经满了,则通过handler所指定的策略来处理任务;一般来说都会把corePoolSize和maximumPoolSize,设置为一样,这样的话,能够减少线程创建的消耗,直接往阻塞队列中取就可以了.
如果采用无界队列,那么maximumPoolSize将会失去作用,此时一般corePoolSize和maximumPoolSize,设置为一样;
keepAliveTime:线程池维护线程所允许的空闲时间。当线程池中的线程数量大于corePoolSize的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了keepAliveTime;
首先是RUNNING状态,然后进入SHUTDOWN和STOP状态,进入SHUTDOWN和STOP状态还有去调整(处理队列任务),调整完最后进入TERMINATED状态。
ctl从11100000000000000000000000000000=-536870912开始,慢慢加1,一直越来越大,最后=111111111111111111111111=-1
worker线程数量最大2^29-1=536870911个,就不能再增加了,所以ctl的范围是(-536870912,-1)一直小于0。
当线程池状态改变时候,改变的是前3位,后29位不变,处于别的状态时候继续使用,原来是1110001101010101010(RUNNING状态),变成SHUTDWON之后ctl是0000001101010101010(SHUTDOWN态),变成STOP之后是0010001101010101010(STOP状态),变成TIDYING后是0100001101010101010(TIDYING态),变成TERMINATED后是0110001101010101010(TERMINATED态)
RUNNING值 < SHUTDOWN值 < STOP值 < TIDYING值 < TERMINATED值,大小顺序,基本符合状态的流转过程。
RUNNING值 <= RUNNING态ctl值 < SHUTDOWN值 <= SHUTDOWN态ctl值 < STOP值 <= STOP态ctl值 < TIDYING值 <= TIDYING态ctl值 < TERMINATED值 <=TERMINATED态ctl值。
每个状态的ctl值大于等于这个状态的标称值,小于下一个标称值。标称值是全0的临界值。rs后面全是0,ctl后面不是0。rs可以用=,ctl不能用=,ctl只能用大于小于。ctl和rs用大于小于判断得到的状态是一个区间值,是多个可能的值。
1.处于正常状态的ctl,ctl=111xxxxxxxx,rs=runStateOf(ctl)=RUNNING=111 0000000000000000,RUNNING<=ctl<SHUTDOWN
2.处于关闭状态的ctl,ctl=000xxxxxxxx,rs=runStateOf(ctl)=SHUTDOWN=000 0000000000000000,SHUTDOWN<=ctl<STOP
3.处于停止状态的ctl,ctl=001xxxxxxxx,rs=runStateOf(ctl)=STOP=001 0000000000000000 ,STOP<=ctl<TIDYING
4.处于调整中的ctl,ctl=010xxxxxxxx,rs=runStateOf(ctl)=TIDYING=010 0000000000000000,TIDYING<=ctl<TERMINATED
5.处于调整完毕的ctl,ctl=011xxxxxxxx,rs=runStateOf(ctl)=TERMINATED=011 0000000000000000 ,TERMINATED<=ctl<=2^31-1
rs只能等于111 0000000000000000(RUNNING),000 0000000000000000(SHUTDOWN),001 0000000000000000(STOP),010 0000000000000000(TIDYING),011 0000000000000000(TERMINATED)
rs>=RUNNING,ctl,rs有5种状态。
rs>=SHUTDOWN,ctl,rs有4种状态。
rs>=STOP,ctl,rs有3种状态。
rs>=TIDYING,ctl,rs有2种状态。
rs>=TERMINATED,ctl,rs有1种状态。
ctl>=RUNNING,ctl,rs有5种状态。
ctl>=SHUTDOWN,ctl,rs有4种状态。
ctl>=STOP,ctl,rs有3种状态。
ctl>=TIDYING,ctl,rs有2种状态。
ctl>=TERMINATED,ctl,rs有1种状态。
int rs = runStateOf(c);//前3位不变,后面29位=0
//c处于RUNNING状态,c=111xxxxxxxxx,rs=111 0000000000000000(RUNNING)
//c处于SHUTDOWN状态,c=000xxxxxxxxx,rs=000 0000000000000000(SHUTDOWN)
//c处于STOP状态,c=001xxxxxxxxx,rs=001 0000000000000000(STOP)
//c处于TIDYING状态,c=010xxxxxxxxx,rs=010 0000000000000000(TIDYING)
//c处于TERMINATED状态,c=011xxxxxxxxx,rs=011 0000000000000000(TERMINATED)
正常运行小于0,SHUTDOWN=0,其他STOP,TIDYING,TERMINATED都是大于0
//C的低29位,跟00011111 11111111 11111111 11111111比较,低29位表示线程池中线程数,最大2^29-1。 private static int workerCountOf(int c) {//对2^29取余,ctl加了多少次1,最大加2^29-1次。表示多少个worker已经在运行了。 return c & CAPACITY;//00011111 11111111 11111111 11111111 } // C的高3位,高3位表示线程池的运行状态。111RUNNING:运行中,接受新任务处理队列中的任务。 //000SHUTDOWN:不接收新任务处理队列中的任务; 001STOP:不接收新任务也不处理队列中的任务还中断正在运行的任务; //010TIDYING:所有的任务都已经终止;011TERMINATED:terminated()方法已经执行完成 private static int runStateOf(int c) { return c & ~CAPACITY;//11100000 00000000 00000000 00000000 }