我们在上面已经算是挺详细地讲了线程池执行任务execute的执行流程和一些细节,在上面频繁地出现了一个字眼,那就是worker实例,那么这个worker究竟是什么呢?里面都包含了一些什么信息,以及worker这个任务究竟是怎么执行的呢?
我们就在这个部分来介绍一下吧,还是直接上源码:
我们可以看到Worker内部类继承AQS同步器并且实现了Runnable接口,所以Worker很明显就是一个可执行任务并且又可以控制中断、起到锁效果的类。
private final class Worker extends AbstractQueuedSynchronizer implements Runnable { /** * This class will never be serialized, but we provide a * serialVersionUID to suppress a javac warning. */ private static final long serialVersionUID = 6138294804551838833L; /** 工作线程,如果工厂失败则为空. */ final Thread thread; /** 初始化任务,有可能为空 */ Runnable firstTask; /** 已完成的任务计数 */ volatile long completedTasks; /** * 创建并初始化第一个任务,使用线程工厂来创建线程 * 初始化有3步 *1、设置AQS的同步状态为-1,表示该对象需要被唤醒 *2、初始化第一个任务 *3、调用ThreadFactory来使自身创建一个线程,并赋值给worker的成员变量thread */ Worker(Runnable firstTask) { setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } //重写Runnable的run方法 /** Delegates main run loop to outer runWorker */ public void run() { //调用ThreadPoolExecutor的runWorker方法 runWorker(this); } // Lock methods // // The value 0 represents the unlocked state. // The value 1 represents the locked state. //代表是否独占锁,0-非独占 1-独占 protected boolean isHeldExclusively() { return getState() != 0; } //重写AQS的tryAcquire方法尝试获取锁 protected boolean tryAcquire(int unused) { //尝试将AQS的同步状态从0改为1 if (compareAndSetState(0, 1)) { //如果改变成,则将当前独占模式的线程设置为当前线程并返回true setExclusiveOwnerThread(Thread.currentThread()); return true; } //否则返回false return false; } //重写AQS的tryRelease尝试释放锁 protected boolean tryRelease(int unused) { //设置当前独占模式的线程为null setExclusiveOwnerThread(null); //设置AQS同步状态为0 setState(0); //返回true return true; } //获取锁 public void lock() { acquire(1); } //尝试获取锁 public boolean tryLock() { return tryAcquire(1); } //释放锁 public void unlock() { release(1); } //是否被独占 public boolean isLocked() { return isHeldExclusively(); } void interruptIfStarted() { Thread t; if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { try { t.interrupt(); } catch (SecurityException ignore) { } } } } 小结写这个线程池就真的是不容易了,历时两个星期,中途有很多的地方不懂,而且《Java并发编程的艺术》的这本书当中对线程池的介绍其实并不算多,所以自己看起来也挺痛苦的,还经常会看了这个方法就不知道为什么要调用这个以及调用这个方法是出何用意。而且在这学习的过程当中,有在怀疑自己的学习方法对不对,因为也有人跟我说不需要一句句去看去分析源码,只需要知道流程就可以了,但是后来还是想想按照自己的学习路线走,多读源码总是有好处的,在这里我也给程序猿一些建议,有自己的学习方法的时候,按照自己的方式坚定走下去。
参考资料方腾飞:《Java并发编程的艺术》
如需转载,请务必注明出处,毕竟一块块搬砖也不是容易的事情。