ForkJoinPool核心数据结构和参数

ForkJoinPool类图

ForkJoinPool核心数据结构和参数_第1张图片

ForkJoinWorkerThreadFactory

ForkJoinWorkerThreadFactory是ForkJoinPool的内部接口,用于创建工作线程ForkJoinWorkerThread对象。

    public static interface ForkJoinWorkerThreadFactory {
        /**
         * Returns a new worker thread operating in the given pool.
         *
         * @param pool the pool this thread works in
         * @return the new worker thread
         * @throws NullPointerException if the pool is null
         */
        public ForkJoinWorkerThread newThread(ForkJoinPool pool);
    }

DefaultForkJoinWorkerThreadFactory

DefaultForkJoinWorkerThreadFactory是ForkJoinWorkerThreadFactory的默认实现类。

    static final class DefaultForkJoinWorkerThreadFactory
        implements ForkJoinWorkerThreadFactory {
        public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
            return new ForkJoinWorkerThread(pool);
        }
    }

InnocuousForkJoinWorkerThreadFactory

InnocuousForkJoinWorkerThreadFactory实现了ForkJoinWorkerThreadFactory,当系统变量中有系统安全管理相关属性时,默认使用这个工厂创建工作线程。

    static final class InnocuousForkJoinWorkerThreadFactory
        implements ForkJoinWorkerThreadFactory {

        /**
         * An ACC to restrict permissions for the factory itself.
         * The constructed workers have no permissions set.
         */
        private static final AccessControlContext innocuousAcc;
        static {
            Permissions innocuousPerms = new Permissions();
            innocuousPerms.add(modifyThreadPermission);
            innocuousPerms.add(new RuntimePermission(
                                   "enableContextClassLoaderOverride"));
            innocuousPerms.add(new RuntimePermission(
                                   "modifyThreadGroup"));
            innocuousAcc = new AccessControlContext(new ProtectionDomain[] {
                    new ProtectionDomain(null, innocuousPerms)
                });
        }

        public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
            return (ForkJoinWorkerThread.InnocuousForkJoinWorkerThread)
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction<ForkJoinWorkerThread>() {
                    public ForkJoinWorkerThread run() {
                        return new ForkJoinWorkerThread.
                            InnocuousForkJoinWorkerThread(pool);
                    }}, innocuousAcc);
        }
    }

SafeForkJoinWorkerThreadFactor

tomcat中的SafeForkJoinWorkerThreadFactor类也实现了ForkJoinWorkerThreadFactory接口。

package org.apache.catalina.startup;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;

public class SafeForkJoinWorkerThreadFactory implements ForkJoinWorkerThreadFactory {
    public SafeForkJoinWorkerThreadFactory() {
    }

    public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
        return new SafeForkJoinWorkerThreadFactory.SafeForkJoinWorkerThread(pool);
    }

    private static class SafeForkJoinWorkerThread extends ForkJoinWorkerThread {
        protected SafeForkJoinWorkerThread(ForkJoinPool pool) {
            super(pool);
            this.setContextClassLoader(ForkJoinPool.class.getClassLoader());
        }
    }
}

EmptyTask

内部占位类,用于替换队列中join的任务。

    static final class EmptyTask extends ForkJoinTask<Void> {
        private static final long serialVersionUID = -7721805057305804111L;
        EmptyTask() { status = ForkJoinTask.NORMAL; } // force done
        public final Void getRawResult() { return null; }
        public final void setRawResult(Void x) {}
        public final boolean exec() { return true; }
    }

ManagedBlocker

为ForkJoinPool中的任务提供扩展管理并行数的接口,一般用在可能会阻塞的任务(如在Phaser中用于等待Phaser到下一个generation)。

    public static interface ManagedBlocker {
        /**
         * Possibly blocks the current thread, for example waiting for
         * a lock or condition.
         *
         * @return {@code true} if no additional blocking is necessary
         * (i.e., if isReleasable would return true)
         * @throws InterruptedException if interrupted while waiting
         * (the method is not required to do so, but is allowed to)
         */
        boolean block() throws InterruptedException;

        /**
         * Returns {@code true} if blocking is unnecessary.
         * @return {@code true} if blocking is unnecessary
         */
        boolean isReleasable();
    }

WorkQueue

ForkJoinPool的核心数据结构,本质上是work-stealing模式的双端任务队列,内部存放ForkJoinTask任务对象。作者不想多个WorkQueue实例或多个队列共享缓存行,@Contended注释会提醒JVM尝试将实例分开。使用@Contended注解修饰防止伪共享。

伪共享状态:缓存系统中是以缓存行(cache line)为单位存储的。缓存行是2的整数幂个连续字节,一般为32-256个字节。最常见的缓存行大小是64个字节。当多线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能,这就是伪共享。

工作线程在运行中产生新的任务(通常是调用了fork方法)时,此时可以把WorkQueue的数据结构视为一个栈,新的任务会放入栈顶;工作线程在处理自己工作队列的任务时,按照FIFO的顺序。

工作线程在处理自己的工作队列的同时,会尝试窃取一个任务(可能是来自于刚刚提交到pool的任务,或是来自于其他工作线程的队列任务),此时可以把WorkQueue的数据结构视为一个FIFO的队列,窃取的任务位于其他线程的工作队列的队首。

ForkJoinPool与内部类WorkQueue共享的一些常量

    // Constants shared across ForkJoinPool and WorkQueue

    // 限定参数
    //低位掩码,也是最大索引位
    static final int SMASK        = 0xffff;
    //工作线程最大容量
    static final int MAX_CAP      = 0x7fff;
    //偶数低位掩码
    static final int EVENMASK     = 0xfffe;
    //workQueue数组最多64个槽位
    static final int SQMASK       = 0x007e;

    // ctl子域和WorkQueue.scanState的掩码和标志位
    //标记是否正在运行任务
    static final int SCANNING     = 1;
    //失活状态 负数
    static final int INACTIVE     = 1 << 31;
    //版本戳,防止ABA问题
    static final int SS_SEQ       = 1 << 16;

    // ForkJoinPool.config和WorkQueue.config的配置信息标记
    //模式掩码
    static final int MODE_MASK    = 0xffff << 16;
    //LIFO队列
    static final int LIFO_QUEUE   = 0;
    //FIFO队列
    static final int FIFO_QUEUE   = 1 << 16;
    //共享模式队列,负数
    static final int SHARED_QUEUE = 1 << 31;

ForkJoinPool中的相关常量和实例字段

    //低位和高位掩码
    private static final long SP_MASK    = 0xffffffffL;
    private static final long UC_MASK    = ~SP_MASK;

    //活跃线程数
    private static final int  AC_SHIFT   = 48;
    //活跃线程数增量
    private static final long AC_UNIT    = 0x0001L << AC_SHIFT;
    //活跃线程数掩码
    private static final long AC_MASK    = 0xffffL << AC_SHIFT;

    //工作线程数
    private static final int  TC_SHIFT   = 32;
    //工作线程数增量
    private static final long TC_UNIT    = 0x0001L << TC_SHIFT;
    //工作线程数掩码
    private static final long TC_MASK    = 0xffffL << TC_SHIFT;
    //创建工作线程标志
    private static final long ADD_WORKER = 0x0001L << (TC_SHIFT + 15); 

    //线程池状态 SHUTDOWN状态为负数
    private static final int  RSLOCK     = 1;
    private static final int  RSIGNAL    = 1 << 1;
    private static final int  STARTED    = 1 << 2;
    private static final int  STOP       = 1 << 29;
    private static final int  TERMINATED = 1 << 30;
    private static final int  SHUTDOWN   = 1 << 31;

    // 实例字段
    //主控制参数
    volatile long ctl;
    //运行状态锁
    volatile int runState;
    //并行度|模式
    final int config
    //用于生成工作线程索引
    int indexSeed;
    //主对象注册信息,WorkQueue
    volatile WorkQueue[] workQueues;
    //线程工厂
    final ForkJoinWorkerThreadFactory factory;
    //每个线程的异常信息
    final UncaughtExceptionHandler ueh;
    //用于创建工作线程的名称
    final String workerNamePrefix;
    //窃取任务总数,也可作为同步监视器
    volatile AtomicLong stealCounter;

	//静态初始化字段
	//线程工厂
    public static final ForkJoinWorkerThreadFactory
        defaultForkJoinWorkerThreadFactory;
	//启动或杀死线程的方法调用者的权限
    private static final RuntimePermission modifyThreadPermission;
	//公共静态pool
    static final ForkJoinPool common;
	//并行度,对应内部common池
    static final int commonParallelism;
	//备用线程数,在tryCompensate中使用
    private static int commonMaxSpares;
	//创建workerNamePrefix(工作线程名称前缀)时的序号
    private static int poolNumberSequence;
	//线程阻塞等待新的任务的超时值(以纳秒为单位),默认两秒
    private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; 
    //空闲超时时间,防止timer未命中
    private static final long TIMEOUT_SLOP = 20L * 1000L * 1000L; 
   	//默认备用线程数
    private static final int DEFAULT_COMMON_MAX_SPARES = 256;
	//阻塞前自旋的次数,用在awaitRunStateLock和awaitWork中
    private static final int SPINS  = 0;
	//indexSeed的增量
    private static final int SEED_INCREMENT = 0x9e3779b9;

ForkJoinPool的内部状态都是通过一个64位的long类型的变量ctl来存储,它由四个16位的子域组成:

  • AC:正在运行工作线程数减去目标并行度,高16位
  • TC:总工作线程数减去目标并行度,中16位
  • SS:栈顶等待线程的版本计数和状态,中低16位
  • ID:栈顶WorkQueue在池中的索引,低16位

ForkJoinPool.WorkQueue中的相关属性

//初始队列容量,2的整数次幂
static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
//最大队列容量
static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M

//实例字段
//Worker状态,小于零:inactive;基数:scanning
volatile int scanState;
//记录前一个栈顶的ctl
int stackPred;
//窃取任务数
int nsteals;
//记录窃取者索引,初始为随机索引
int hint;
//池索引和模式
int config;
//1:locked;< 0:terminate;else 0
volatile int qlock;
//下一个pool操作的索引(栈底/队列头)
volatile int base;
//下一个push操作的索引(栈顶/队列尾)
int top;
//任务数组
ForkJoinTask<?>[] array;
//the containing pool (may be null)
final ForkJoinPool pool;
//当前工作队列的工作线程,共享模式下为null
final ForkJoinWorkerThread owner;
//调用park阻塞期间为owner,其他情况为null
volatile Thread parker;
//记录join过来的任务
volatile ForkJoinTask<?> currentJoin;
//记录从其他工作队列窃取过来的任务
volatile ForkJoinTask<?> currentSteal;

你可能感兴趣的:(多线程,多线程,java)