科普文:JUC系列之ForkJoinPool源码解读ForkJoinWorkerThread

embedded/2024/10/18 22:33:45/

科普文:JUC系列之ForkJoinPool基本使用及原理解读-CSDN博客

科普文:JUC系列之ForkJoinPool源码解读概叙-CSDN博客

科普文:JUC系列之ForkJoinPool源码解读WorkQueue-CSDN博客

科普文:JUC系列之ForkJoinPool源码解读ForkJoinTask-CSDN博客

ForkJoinWorker>ForkJoinWorkerThread实际上非常简单,就是结合ForkJoinPool,然后根据其需要,创建合适的线程的过程。这里面值得我们借鉴的是,如果需要创建无其他访问权限的线程,实际上这两种线程大部分内容都是相同的,因此可以通过继承来复用大部分代码。之后定义两个factory,让最终的用户根据需要选择factory。

一、类结构及其成员变量

1.1 类结构和注释

类结构代码如下:

public class ForkJoinWorker>ForkJoinWorkerThread extends Thread {}

ForkJoinWorker>ForkJoinWorkerThread继承了Thread类,ForkJoinWorker>ForkJoinWorkerThread是由ForkJoinPool管理的线程,该线程执行ForkJoinTask。此类仅可做为扩展功能的需要而被集成,因为没有提供可以调度或者可重新的方法。但是,你可以覆盖主任务处理循环周围初始化和终止方法。如果确实创建了这个类的子类,还需要在ForkJoinPool中提供自定义的ForkJoinWorker>ForkJoinWorkerThreadFactory来使用。

1.2 常量

主要有两个:

final ForkJoinPool pool;                // the pool this thread works in
final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics

ForkJoinWorker>ForkJoinWorkerThreads由ForkJoinPools管理,并执行ForkJoinTasks。请参见ForkJoinPool的内部文档。此类仅仅维护了指向pool和WorkQueue的链接。pool字段在构造的时候直接设置。但是直到对registerWorker调用完成之后,才设置workQueue字段。这将导致可见性竞争,可以通过要求workQueue字段仅由其所属线程访问来规避这个问题。对于InnocuousForkJoinWorker>ForkJoinWorkerThread子类的支持,要求我们在此处和子类中破坏很多封装,通过Unsafe以访问和设置Thread字段。

这是两个final修饰的常量,智能初始化一次。

二、构造函数

2.1 ForkJoinWorker>ForkJoinWorkerThread(ForkJoinPool pool)

protected ForkJoinWorker>ForkJoinWorkerThread(ForkJoinPool pool) {// Use a placeholder until a useful name can be set in registerWorkersuper("aForkJoinWorker>ForkJoinWorkerThread");this.pool = pool;this.workQueue = pool.registerWorker(this);
}

其构造函数主要是创建一个在给定pool中的ForkJoinWorker>ForkJoinWorkerThread。构造函数中最主要的方法就是registerWorker。

2.2 ForkJoinWorker>ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup, AccessControlContext acc)

ForkJoinWorker>ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,AccessControlContext acc) {super(threadGroup, null, "aForkJoinWorker>ForkJoinWorkerThread");U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);eraseThreadLocals(); // clear before registeringthis.pool = pool;this.workQueue = pool.registerWorker(this);
}

这个方法需要注意的是,采用unSafe方法,在这个类的INHERITEDACCESSCONTROLCONTEXT位置处,设置传入的AccessControlContext对象。
之后调用方法eraseThreadLocals将threadLocals清除。
之后与同用的构造函数一致。
擦除ThreadLocal也是采用UnSafe来完成。通过putObject将ThreadLocals的位置设置为null。

final void eraseThreadLocals() {U.putObject(this, THREADLOCALS, null);U.putObject(this, INHERITABLETHREADLOCALS, null);
}

实际上这个方法将会提供给InnocuousForkJoinWorker>ForkJoinWorkerThread继承的时候使用。

三、核心方法

3.1 run

做为Thread,最重要的就是run方法,我们来看看ForkJoinWorker>ForkJoinWorkerThread的实现:

public void run() {//如果workQueue为空,则抛出异常if (workQueue.array == null) { // only run onceThrowable exception = null;try {//调用onStart方法onStart();//调用pool的runWorker方法,运行workQueuepool.runWorker(workQueue);} catch (Throwable ex) {exception = ex;} finally {//操作完之后处理try {//调用onTermination方法onTermination(exception);} catch (Throwable ex) {//如果出现异常,则进行异常处理if (exception == null)exception = ex;} finally {//最终需要指向deregister方法pool.deregisterWorker(this, exception);}}}
}

runWorker方法实际上是对workQueue结合随机魔数,选择一个workQueue进行遍历,调用scan方法,如果不为空则执行,反之则wait。
其中registerWorker与deregisterWorker方法 ,我们可以参考前面的ForkJoinPool源码解读。

3.2 定义的可扩展方法

由于ForkJoinWorker>ForkJoinWorkerThread还支持继承扩展,因此在此定义了两个扩展的方法:

protected void onStart() {
}protected void onTermination(Throwable exception) {
}

这两个方法用于执行之前和之后,onStart用于run实际执行之前,执行一些初始化操作。onTermination用于run实际执行之后,执行一些清理操作。

四、内部类InnocuousForkJoinWorker>ForkJoinWorkerThread

这个类就是继承了ForkJoinWorker>ForkJoinWorkerThread的一个实现类。此类定义了一个没有任何权限、也非用户定义的任何线程组的线程。这个线程在运行完每个top的task之后,会擦除所有的ThreadLocals。

源码如下:

static final class InnocuousForkJoinWorker>ForkJoinWorkerThread extends ForkJoinWorker>ForkJoinWorkerThread {/** The ThreadGroup for all InnocuousForkJoinWorker>ForkJoinWorkerThreads */private static final ThreadGroup innocuousThreadGroup =createThreadGroup();/** An AccessControlContext supporting no privileges */private static final AccessControlContext INNOCUOUS_ACC =new AccessControlContext(new ProtectionDomain[] {new ProtectionDomain(null, null)});InnocuousForkJoinWorker>ForkJoinWorkerThread(ForkJoinPool pool) {super(pool, innocuousThreadGroup, INNOCUOUS_ACC);}@Override // to erase ThreadLocalsvoid afterTopLevelExec() {eraseThreadLocals();}@Override // to always report system loaderpublic ClassLoader getContextClassLoader() {return ClassLoader.getSystemClassLoader();}@Override // to silently failpublic void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }@Override // paranoicallypublic void setContextClassLoader(ClassLoader cl) {throw new SecurityException("setContextClassLoader");}private static ThreadGroup createThreadGroup() {try {sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe();Class<?> tk = Thread.class;Class<?> gk = ThreadGroup.class;long tg = u.objectFieldOffset(tk.getDeclaredField("group"));long gp = u.objectFieldOffset(gk.getDeclaredField("parent"));ThreadGroup group = (ThreadGroup)u.getObject(Thread.currentThread(), tg);while (group != null) {ThreadGroup parent = (ThreadGroup)u.getObject(group, gp);if (parent == null)return new ThreadGroup(group,"InnocuousForkJoinWorker>ForkJoinWorkerThreadGroup");group = parent;}} catch (Exception e) {throw new Error(e);}// fall through if null as cannot-happen safeguardthrow new Error("Cannot create ThreadGroup");}
}

AccessControlContext INNOCUOUS_ACC 定义了一个不支持任何特权访问的AccessControlContext。这个类会创建一个单独的threadGroup,以确保其不属于任何一个用户创建的ThreadGroup。

五、ForkJoinPool中创建工作线程的过程

此时再来结合ForkJoinPool中的ForkJoinWorker>ForkJoinWorkerThreadFactory,就能明白ForkJoinThread的创建意义了。ForkJoinPool根据访问权限的需要,定义了采用默认的创建方法,还是创建InnocuousForkJoinWorker>ForkJoinWorkerThread。

5.1 makeCommonPool创建过程

ForkJoinPool重的makeCommPool,有如下代码:

if (factory == null) {if (System.getSecurityManager() == null)factory = defaultForkJoinWorker>ForkJoinWorkerThreadFactory;else // use security-managed defaultfactory = new InnocuousForkJoinWorker>ForkJoinWorkerThreadFactory();
}

这里也就是说,如果System.getSecurityManager()为null,则返回默认的ThreadFactory,而不为null,则说, 使用了默认的安全管理级别,因此将创建InnocuousForkJoinWorker>ForkJoinWorkerThreadFactory。

5.2 createWorker创建过程

ForkJoinWorker>ForkJoinWorkerThreadFactory fac = factory;
try {if (fac != null && (wt = fac.newThread(this)) != null) {wt.start();return true;}
} catch (Throwable rex) {ex = rex;
}

也就是说,createWorker根据ForkJoinWorker>ForkJoinWorkerThreadFactory的实现类来创建。

5.3 InnocuousForkJoinWorker>ForkJoinWorkerThreadFactory

static final class InnocuousForkJoinWorker>ForkJoinWorkerThreadFactoryimplements ForkJoinWorker>ForkJoinWorkerThreadFactory {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 ForkJoinWorker>ForkJoinWorkerThread newThread(ForkJoinPool pool) {return (ForkJoinWorker>ForkJoinWorkerThread.InnocuousForkJoinWorker>ForkJoinWorkerThread)java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<ForkJoinWorker>ForkJoinWorkerThread>() {public ForkJoinWorker>ForkJoinWorkerThread run() {return new ForkJoinWorker>ForkJoinWorkerThread.InnocuousForkJoinWorker>ForkJoinWorkerThread(pool);}}, innocuousAcc);}
}

5.4 DefaultForkJoinWorker>ForkJoinWorkerThreadFactory

static final class DefaultForkJoinWorker>ForkJoinWorkerThreadFactoryimplements ForkJoinWorker>ForkJoinWorkerThreadFactory {public final ForkJoinWorker>ForkJoinWorkerThread newThread(ForkJoinPool pool) {return new ForkJoinWorker>ForkJoinWorkerThread(pool);}
}


http://www.ppmy.cn/embedded/91112.html

相关文章

XQuery 术语

XQuery 术语 XQuery 是一种用于查询 XML 数据的语言,它基于 XML 的数据模型,并允许用户以声明式的方式查询和转换 XML 数据。XQuery 1.0 在 2007 年成为 W3C 推荐标准,并在随后的版本中进行了更新和扩展。本文将介绍一些 XQuery 中的基本术语和概念。 基本术语 序列(Seq…

STL—容器—list【list的介绍和基本使用】【list的迭代器失效问题】

STL—容器—list list的使用并不难&#xff0c;有了之前使用string和vector的基础后&#xff0c;学习起来并不难。因此这里不在详细的讲解如何使用&#xff0c;而是大致的将其基本接口都熟悉一下 1.list介绍 list的文档介绍 list是可以在常数范围内在任意位置进行插入和删除…

关于自动化安装

设备 1.rhel7主机 2.开启图形化 init5 3.配置网络可用 4.关闭vmware dhcp 功能 配置 cat /root/anaconda-ks.cfg #查看这个文件完成虚拟机安装时会自动生成 yum install system-config-kickstart #安装图形化生成kickstart自动安装脚本工具 system-config-kickstart #启用…

【Mind+】掌控板入门教程05 心情灯

大自然的各种色彩使人产生各种感觉&#xff0c;心理学家认为&#xff0c;不同的颜色会让人产生不同的情绪。比如&#xff0c;红色通常给人刺激、热情和幸福的感觉&#xff0c;而绿色作为自然界中草原和森林的颜色&#xff0c;给人以理想、年轻、新鲜的感觉&#xff0c;蓝色则让…

计算机网络基础之网络套接字socket编程(初步认识UDP、TCP协议)

绪论​ “宿命论是那些缺乏意志力的弱者的借口。 ——罗曼&#xff0e;罗兰”&#xff0c;本章是为应用层打基础&#xff0c;因为在写应用层时将直接通过文本和代码的形式来更加可视化的理解网络&#xff0c;本章主要写的是如何使用网络套接字和udp、tcp初步认识。 话不多说安…

【C++】二维数组 数组名

二维数组名用途 1、查看所占内存空间 2、查看二维数组首地址 针对第一种用途&#xff0c;还可以计算数组有多少行、多少列、多少元素 针对第二种用途&#xff0c;数组元素、行数、列数都是连续的&#xff0c;且相差地址是有规律的 下面是一个实例 #include<iostream&g…

JS-03.基础语法-变量

一、JavaScript中用var关键字&#xff08;variable的缩写&#xff09;来声明变量。 1.特点一&#xff1a;通过var声明的变量是一个全局变量&#xff0c;在代码块外部也能够拿到 2.特点二&#xff1a;通过var声明的变量可以重复定义 二、JavaScript是一门弱类型语言&…

Redis01——Redis简介

目录 NOSQL与SQL的差异 数据结构&#xff1a;结构化 VS 非结构化 数据关联&#xff1a;关系型 VS 非关系型 数据查询&#xff1a;SQL查询 VS 非SQL查询 事务特性&#xff1a;满足事 VS 没有完全满足 Redis 简介 Redis 安装 Redis 数据结构简介 Redis 常用命令&#xff…