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

news2024/11/22 15:19:16

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

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

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

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

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

一、类结构及其成员变量

1.1 类结构和注释

类结构代码如下:

public class ForkJoinWorkerThread extends Thread {
    
}

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

1.2 常量

主要有两个:

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

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

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

二、构造函数

2.1 ForkJoinWorkerThread(ForkJoinPool pool)

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

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

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

ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
                     AccessControlContext acc) {
    super(threadGroup, null, "aForkJoinWorkerThread");
    U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
    eraseThreadLocals(); // clear before registering
    this.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);
}

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

三、核心方法

3.1 run

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

public void run() {
    //如果workQueue为空,则抛出异常
    if (workQueue.array == null) { // only run once
        Throwable exception = null;
        try {
            //调用onStart方法
            onStart();
            //调用pool的runWorker方法,运行workQueue
            pool.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 定义的可扩展方法

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

protected void onStart() {
}

protected void onTermination(Throwable exception) {
}

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

四、内部类InnocuousForkJoinWorkerThread

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

源码如下:

static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
    /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
    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)
            });

    InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
        super(pool, innocuousThreadGroup, INNOCUOUS_ACC);
    }

    @Override // to erase ThreadLocals
    void afterTopLevelExec() {
        eraseThreadLocals();
    }

    @Override // to always report system loader
    public ClassLoader getContextClassLoader() {
        return ClassLoader.getSystemClassLoader();
    }

    @Override // to silently fail
    public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }

    @Override // paranoically
    public 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,
                                           "InnocuousForkJoinWorkerThreadGroup");
                group = parent;
            }
        } catch (Exception e) {
            throw new Error(e);
        }
        // fall through if null as cannot-happen safeguard
        throw new Error("Cannot create ThreadGroup");
    }
}

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

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

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

5.1 makeCommonPool创建过程

再ForkJoinPool重的makeCommPool,有如下代码:

if (factory == null) {
    if (System.getSecurityManager() == null)
        factory = defaultForkJoinWorkerThreadFactory;
    else // use security-managed default
        factory = new InnocuousForkJoinWorkerThreadFactory();
}

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

5.2 createWorker创建过程

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

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

5.3 InnocuousForkJoinWorkerThreadFactory

static final class InnocuousForkJoinWorkerThreadFactory
    implements 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 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);
    }
}

5.4 DefaultForkJoinWorkerThreadFactory

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1983386.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

复现sql注入漏洞

Less-1 字符型注入 页面如下&#xff1a; 我们先输入“?id1”看看结果&#xff1a; 页面显示错误信息中显示提交到sql中的“1”在通过sql语句构造后形成“1" LIMIT 0, 1”&#xff0c;其中多了一个“”&#xff0c;那么&#xff0c;我们的任务就是——逃脱出单引号的控制…

petalinux安装成功后登录Linux出现密码账号不正确

安装完Linux系统后发现登陆开发板上的Linux系统登陆一直错误&#xff0c;但你输入的账号和密码确确实实是“root”&#xff0c;但仍然一直在重复登陆。 这个时候就会怀疑自己是不是把密码改了&#xff0c;导致错误&#xff0c;然后又重新创建petalinux工程。 其实这个时候不需…

2024年第二季度HDD出货量和容量分析

概述 根据Trendfocus, Inc.发布的《SDAS: HDD Information Service CQ2 24 Quarterly Update – Executive Summary》报告&#xff0c;2024年第二季度硬盘驱动器(HDD)出货量和容量均出现了显著增长。总体来看&#xff0c;HDD出货量较上一季度增长2%&#xff0c;达到3028万块&a…

MySQLDM笔记-查询库中是否存在列出的表名及查询库中列出的不存在的表名

如下表名&#xff1a; aaa,bb,cc,ccs,dds,csdf,csdfs,sdfa,werwe,csdfsd 在MySQL库中&#xff0c;查询哪些表名在数据库中 SELECT table_name FROM information_schema.tables WHERE table_schema your_database_name_here AND table_name IN (aaa, bb, cc, ccs, dds, csdf…

硬件电路学习记录(七)——全面概述MOS管

目录 1.NMOS&#xff1a; 工作原理 特性 应用 2.PMOS&#xff1a; PMOS的结构与工作原理 结构 工作原理 增强型PMOS与耗尽型PMOS 增强型PMOS&#xff08;Enhancement Mode PMOS&#xff09; 耗尽型PMOS&#xff08;Depletion Mode PMOS&#xff09; 应用 PMOS的工…

不同角色路由权限配置(六)

一、启用方式 配置开启config/config.ts。同时需要 src/access.ts 提供权限配置 export default {access: {},// access 插件依赖 initial State 所以需要同时开启initialState: {}, };这里以扩展的路由配置为例&#xff0c;配置只有admin权限才能查看的页面 1、在src/acces…

新华三H3CNE网络工程师认证—路由基础

我们的一个个网络其实是由不同的广播域构成的&#xff0c;而路由器的作用就是用来连接不同的广播域。那么不同广播域之间是如何通信的呢&#xff1f;比如有三个网段&#xff0c;1.0、2.0和3.0。网段1.0和网段2.0通信需要构造数据包&#xff0c;源是1.1&#xff0c;目标去往2.1。…

3.6 上下文菜单

上下文菜单 上下文菜单就是常见的右键菜单(弹出式菜单)。 显示上下文菜单&#xff0c;阻塞函数 BOOL TrackPopupMenu(HMENU hMenu, //菜单句柄UINT uFlags, //显示方式int x, //水平位置&#xff0c;屏幕坐标系int y, //垂直位置&#xff0c;屏幕坐标系UINT nReserved, //…

Cartopy简介和安装

Cartopy 是一个开源免费的第三方 Python 扩展包&#xff0c;由英国气象办公室的科学家们开发&#xff0c;支持 Python 2.7 和 Python 3&#xff0c;致力于使用最简单直观的方式生成地图&#xff0c;并提供对 matplotlib 友好的协作接口。初学Cartopy&#xff0c;欢迎指正&#…

Leetcode—186. 反转字符串中的单词 II【中等】Plus

2024每日刷题&#xff08;152&#xff09; Leetcode—186. 反转字符串中的单词 II 实现代码 class Solution { public:void reverseW(vector<char>& s, int n) {int i 0;int j 0;while(i < n) {while(i < j || i < n && s[i] ) {i;}while(j &…

Spring自动装配的局限

Spring自动装配的局限 1. 覆盖风险2. 类型限制3. 精确性挑战4. 维护难度 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Spring的自动装配功能虽然为开发者带来了极大的便利&#xff0c;但在实际应用中也存在一些不容忽视的局限。 1. 覆盖…

大数据-65 Kafka 高级特性 分区 Broker自动再平衡 ISR 副本 宕机恢复再重平衡 实测

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

科普小课堂|LCD 问题排查思路解析

&#xff08;ELF 1开发板、ELF 1S开发板及显示屏&#xff09; 在嵌入式系统开发中&#xff0c;液晶显示器&#xff08;LCD&#xff09;作为人机交互的重要界面&#xff0c;其稳定性和可靠性至关重要。然而在实际应用中&#xff0c;LCD难免会遇到各种问题。今天和各位小伙伴分享…

Javascript常见算法(二)【学习】

动态规划 斐波那契数列&#xff1a; 经典的动态规划问题&#xff0c;每个数是前两个数的和。 斐波那契数列&#xff08;Fibonacci sequence&#xff09;是一个非常著名的数列&#xff0c;其中每个数是前两个数的和&#xff0c;序列以0和1开始。在JavaScript中&#xff0c;有多…

【数据结构】顺序表详解以及实现(C语言实现)

目录 前言&#xff1a; 顺序表的特点&#xff1a; 顺序表简介&#xff1a; 顺序表具体实现&#xff1a; 1.初始化 2.销毁 3.检查空间容量 4.头插和尾插 5.头删和尾删 6.打印 7.指定位置插入 8.指定位置删除 9. 查找是否有对应元素 顺序表是线性表的存储结构&#xff…

8月5日笔记

8月5日 nmap命令使用 nmap四种基本功能&#xff1a;端口扫描、主机探测、服务识别、系统识别。 nmap ip默认情况下&#xff0c;nmap 会对目标执行 TCP 端口扫描&#xff0c;尝试找出哪些端口是开放的&#xff0c;并提供关于这些端口上运行的服务的一些基本信息。 其他参数&…

Html5总结

前端学习 html决定页面的结构css决定页面的样式js决定页面的行为 Html5 1.文本格式化标签&#xff08;熟记&#xff09; 你在网页中&#xff0c;有时需要为文字设置粗体、斜体或下划线效果&#xff0c;这时就需要用到HTML中的文本格式化标记 2.标签属性 例如&#xff1a; …

Java SDK开发(SpringBoot Starter)

SDK开发 开发starter的好处&#xff1a;引入starter之后&#xff0c;可以在配置文件中配置&#xff0c;自动生成客户端使用。 步骤 1. 创建一个初始化SpringBoot项目&#xff0c;选择相关依赖&#xff1a; Lombook&#xff1a;日志注解 第二个注解是为了关键词提示用的&…

Java:多线程(同步死锁,锁原子变量,线程通信,线程池)

5&#xff0c;同步和死锁 5.1&#xff0c;Synchronized&#xff0c;Lock 修饰一个代码块&#xff0c;被修饰的代码块称为同步语句块&#xff0c;其作用的范围是大括号{}括起来的代码&#xff0c;作用的对象是调用这个代码块的对象&#xff1b;修饰一个方法&#xff0c;被修饰的…

如何使用极狐GitLab 实现最小权限访问?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…