JUC并发包

ThreadPoolExecutor源码历险-不可变内部类Wor

2021-01-13  本文已影响0人  于情于你

    上一篇说了ThreadPoolExecutor里面的位运算,在后边的源码介绍中就会看到有很多地方调用了那些位运算方法,更加深刻的体会到设计的精妙。
    这一篇来搞一下线程池中的Worker

Worker是啥?

    Worker是线程池中的工作者,一个Worker绑定了一个线程,同时也是一个可以执行的任务,Worker继承了AbstractQueuedSynchronizer实现了一个不可重入锁。这里贴一张图有助于更好的体会Worker的作用。


image.png

    下面是Worker的源码,注释已经写在代码里了。其中的run方法,里面的runWorker(),我们在下一篇,主流程常用方法里面会引出来一起看一下。

 private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
       
        private static final long serialVersionUID = 6138294804551838833L;

        // 执行任务的线程,如果ThreadFactory失败可能为null
        final Thread thread;
        // 线程执行的任务
        Runnable firstTask;
        // 每个Worker完成的任务数
        volatile long completedTasks;

        // 根据给定的任务创建一个Worker
        Worker(Runnable firstTask) {
            setState(-1); // 设置为-1防止在执行runWorker之前被打断。interruptIfStarted方法只能打断state>=0的
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

        public void run() {
            runWorker(this);
        }
      // ============重写AQS的方法START============
        // Lock methods
        // state=0 代表没有锁 1表示有锁
        protected boolean isHeldExclusively() {
            return getState() != 0;
        }
    
        // 尝试加锁
        protected boolean tryAcquire(int unused) {
          
            // status的值更新为1
            if (compareAndSetState(0, 1)) {
                
                 // 设置当前线程持有锁
                setExclusiveOwnerThread(Thread.currentThread());

                // 加锁成功
                return true;
            }
            // 加锁失败
            return false;
        }
      
        // 尝试释放锁
        protected boolean tryRelease(int unused) {
           // 释放拥有独占访问权的线程
            setExclusiveOwnerThread(null);
           // state变更为0,释放锁
            setState(0);
            return true;
        }
      // ============重写AQS的方法END============

        // ============自己定义的方法 START============
        public void lock()        { acquire(1); }
        public boolean tryLock()  { return tryAcquire(1); }
        public void unlock()      { release(1); }
        public boolean isLocked() { return isHeldExclusively(); }
      

        // 中断线程(主要是用于shutdownNow方法)
        void interruptIfStarted() {
            Thread t;
            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
                try {
                    t.interrupt();
                } catch (SecurityException ignore) {
                }
            }
        }
    }
        // ============自己定义的方法 END============

    读完Worker的源码我有一个问题没明白,如果大家有知道的可以评论告诉我一下,互相学习。我也会在工作之余,想尽一切办法解决这个问题。

    线程池Worker为什么需要加锁?为什么需要非可重入锁?

上一篇下一篇

猜你喜欢

热点阅读