美文网首页JUC并发包
ThreadPoolExecutor源码历险-不可变内部类Wor

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

作者: 于情于你 | 来源:发表于2021-01-13 00:34 被阅读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为什么需要加锁?为什么需要非可重入锁?

    相关文章

      网友评论

        本文标题:ThreadPoolExecutor源码历险-不可变内部类Wor

        本文链接:https://www.haomeiwen.com/subject/svveaktx.html