当前位置: 首页 > news >正文

react源码中的fiber架构

先看一下FiberNode在源码中的样子

FiberNode

// packages/react-reconciler/src/ReactFiber.old.js
function FiberNode(tag: WorkTag,  pendingProps: mixed,  key: null | string,  mode: TypeOfMode,
) {// Instancethis.tag = tag;this.key = key;this.elementType = null;this.type = null;this.stateNode = null;// Fiberthis.return = null;this.child = null;this.sibling = null;this.index = 0;this.ref = null;this.pendingProps = pendingProps;this.memoizedProps = null;this.updateQueue = null;this.memoizedState = null;this.dependencies = null;this.mode = mode;// Effectsthis.flags = NoFlags;this.nextEffect = null;this.firstEffect = null;this.lastEffect = null;this.lanes = NoLanes;this.childLanes = NoLanes;this.alternate = null;if (enableProfilerTimer) {// Note: The following is done to avoid a v8 performance cliff.//// Initializing the fields below to smis and later updating them with// double values will cause Fibers to end up having separate shapes.// This behavior/bug has something to do with Object.preventExtension().// Fortunately this only impacts DEV builds.// Unfortunately it makes React unusably slow for some applications.// To work around this, initialize the fields below with doubles.//// Learn more about this here:// https://github.com/facebook/react/issues/14365// https://bugs.chromium.org/p/v8/issues/detail?id=8538this.actualDuration = Number.NaN;this.actualStartTime = Number.NaN;this.selfBaseDuration = Number.NaN;this.treeBaseDuration = Number.NaN;// It's okay to replace the initial doubles with smis after initialization.// This won't trigger the performance cliff mentioned above,// and it simplifies other profiler code (including DevTools).this.actualDuration = 0;this.actualStartTime = -1;this.selfBaseDuration = 0;this.treeBaseDuration = 0;}if (__DEV__) {// This isn't directly used but is handy for debugging internals:...}
}
  • 我们看FiberNode这个构造函数里面只是赋值,我们再找一下链路上的Fiber,我们发现在函数createFiber的返回值类型里面出现了Fiber类型,所以
// packages/react-reconciler/src/ReactInternalTypes.js
export type Fiber = {|// These first fields are conceptually members of an Instance. This used to// be split into a separate type and intersected with the other Fiber fields,// but until Flow fixes its intersection bugs, we've merged them into a// single type.// An Instance is shared between all versions of a component. We can easily// break this out into a separate object to avoid copying so much to the// alternate versions of the tree. We put this on a single object for now to// minimize the number of objects created during the initial render.// dom节点的相关信息tag: WorkTag,// 组件的类型key: null | string, // 唯一值elementType: any,// 元素类型// 判定fiber节点的类型,用于difftype: any,// 真实 dom 节点stateNode: any,// Conceptual aliases// parent : Instance -> return The parent happens to be the same as the// return fiber since we've merged the fiber and instance.// Remaining fields belong to Fiber// fiber 链表树return: Fiber | null, // 父 fiberchild: Fiber | null, // 第一个子 fibersibling: Fiber | null, // 下一个兄弟 fiberindex: number, // 在父 fiber 下面的子 fiber 中的下标// The ref last used to attach this node.// I'll avoid adding an owner field for prod and model that as functions.ref:| null| (((handle: mixed) => void) & {_stringRef: ?string, ...})| RefObject,// 计算 state 和 props 渲染pendingProps: any, // 本次渲染需要使用的 propsmemoizedProps: any, // 上次渲染使用的 propsupdateQueue: mixed, // 用于状态更新、回调函数、DOM更新的队列memoizedState: any, // 上次渲染后的 state 状态dependencies: Dependencies | null, // contexts、events 等依赖// Bitfield that describes properties about the fiber and its subtree. E.g.// the ConcurrentMode flag indicates whether the subtree should be async-by-// default. When a fiber is created, it inherits the mode of its// parent. Additional flags can be set at creation time, but after that the// value should remain unchanged throughout the fiber's lifetime, particularly// before its child fibers are created.mode: TypeOfMode,// Effectflags: Flags, // 记录更新时当前 fiber 的副作用(删除、更新、替换等)状态subtreeFlags: Flags, // 当前子树的副作用状态deletions: Array<Fiber> | null, // 要删除的子 fibernextEffect: Fiber | null, // 下一个有副作用的 fiberfirstEffect: Fiber | null, // 指向第一个有副作用的 fiberlastEffect: Fiber | null, // 指向最后一个有副作用的 fiber // 渲染优先级lanes: Lanes,childLanes: Lanes,// This is a pooled version of a Fiber. Every fiber that gets updated will// eventually have a pair. There are cases when we can clean up pairs to save// memory if we need to.alternate: Fiber | null,// 指向 workInProgress fiber 树中对应的节点// Time spent rendering this Fiber and its descendants for the current update.// This tells us how well the tree makes use of sCU for memoization.// It is reset to 0 each time we render and only updated when we don't bailout.// This field is only set when the enableProfilerTimer flag is enabled.actualDuration?: number,// If the Fiber is currently active in the "render" phase,// This marks the time at which the work began.// This field is only set when the enableProfilerTimer flag is enabled.actualStartTime?: number,// Duration of the most recent render time for this Fiber.// This value is not updated when we bailout for memoization purposes.// This field is only set when the enableProfilerTimer flag is enabled.selfBaseDuration?: number,// Sum of base times for all descendants of this Fiber.// This value bubbles up during the "complete" phase.// This field is only set when the enableProfilerTimer flag is enabled.treeBaseDuration?: number,// Conceptual aliases// workInProgress : Fiber ->  alternate The alternate used for reuse happens// to be the same as work in progress.// __DEV__ only_debugID?: number,_debugSource?: Source | null,_debugOwner?: Fiber | null,_debugIsCurrentlyTiming?: boolean,_debugNeedsRemount?: boolean,// Used to verify that the order of hooks does not change between renders._debugHookTypes?: Array<HookType> | null,
|};

相关参考视频讲解:进入学习

  • 整个fiber架构看起来可以分为dom信息、副作用、优先级、链表树等几个模块,那我们依次来拆分一下

dom信息节点

tag: WorkTag
我们看到这个`tag``WorkTag`类型,用来区分`React`组件的类型
// packages/react-reconciler/src/ReactWorkTags.js
export type WorkTag =| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20| 21| 22| 23| 24;export const FunctionComponent = 0;
export const ClassComponent = 1;
export const IndeterminateComponent = 2; // Before we know whether it is function or class
export const HostRoot = 3; // Root of a host tree. Could be nested inside another node.
export const HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
export const HostComponent = 5;
export const HostText = 6;
export const Fragment = 7;
export const Mode = 8;
export const ContextConsumer = 9;
export const ContextProvider = 10;
export const ForwardRef = 11;
export const Profiler = 12;
export const SuspenseComponent = 13;
export const MemoComponent = 14;
export const SimpleMemoComponent = 15;
export const LazyComponent = 16;
export const IncompleteClassComponent = 17;
export const DehydratedFragment = 18;
export const SuspenseListComponent = 19;
export const FundamentalComponent = 20;
export const ScopeComponent = 21;
export const Block = 22;
export const OffscreenComponent = 23;
export const LegacyHiddenComponent = 24;

上述代码,区分了组件的类型,在后期协调阶段beginWorkcompleteWork的流程里根据不同的类型组件去做不同的fiber节点的处理

key: null | string、type: any
key为唯一值,type为与fiber关联的节点类型,都用于beginWork流程里面的reconcileChildren流程
elementType
元素类型
stateNode
- stateNode 用于记录当前 fiber 所对应的真实 dom 节点或者当前虚拟组件的实例。
- 便于实现Ref
- 便于追踪Rdom

fiber 链表树

fiber链表树里面有四个字段returnchildsiblingindex

  • return:指向父节点,没有父节点则为null。
  • child:指向下一个子节点,没有下一个子节点则为null。
  • sibling:指向兄弟节点,没有下一个兄弟节点则为null。
  • index:父fiber下面的子fiber下标
    通过这些字段那么我们可以形成一个闭环链表,举个栗子。
<div className='box'><h1 className='title' style={{'color':'red'}}>React源码解析</h1><ul><li>第一章</li><li>第二章</li><li>第三章</li><li>第四章</li></ul>
</div>

根据上面的代码所对应的fiber链表树结构就是:

在这里插入图片描述

副作用相关

所谓副作用就是一套流程中我们不期望发生的情况。举个通俗的例子就是我们生活中去学游泳,在学会游泳的过程中呛了几口水,这个呛了几口水相对于成功学会游泳来说就是副作用,回归到react代码中,我们通过某些手段去修改propsstate等数据,数据修改完毕之后,但是同时引起了dom不必要的变化,那么这个变化就是副作用,当然这个副作用是必然存在的,就像游泳一样,必然会呛几口水,哈哈。

flags: Flags
记录当前节点通过`reconcileChildren`之后的的副作用,如插入,删除等

例如Placement,表示插入,也叫新增。Deletion表示删除,Update表示更新

export type Flags = number;// Don't change these two values. They're used by React Dev Tools.
export const NoFlags = /*                      */ 0b000000000000000000;
export const PerformedWork = /*                */ 0b000000000000000001;// You can change the rest (and add more).
export const Placement = /*                    */ 0b000000000000000010;
export const Update = /*                       */ 0b000000000000000100;
export const PlacementAndUpdate = /*           */ 0b000000000000000110;
export const Deletion = /*                     */ 0b000000000000001000;
export const ContentReset = /*                 */ 0b000000000000010000;
export const Callback = /*                     */ 0b000000000000100000;
export const DidCapture = /*                   */ 0b000000000001000000;
export const Ref = /*                          */ 0b000000000010000000;
export const Snapshot = /*                     */ 0b000000000100000000;
export const Passive = /*                      */ 0b000000001000000000;
// TODO (effects) Remove this bit once the new reconciler is synced to the old.
export const PassiveUnmountPendingDev = /*     */ 0b000010000000000000;
export const Hydrating = /*                    */ 0b000000010000000000;
export const HydratingAndUpdate = /*           */ 0b000000010000000100;// Passive & Update & Callback & Ref & Snapshot
export const LifecycleEffectMask = /*          */ 0b000000001110100100;// Union of all host effects
export const HostEffectMask = /*               */ 0b000000011111111111;// These are not really side effects, but we still reuse this field.
export const Incomplete = /*                   */ 0b000000100000000000;
export const ShouldCapture = /*                */ 0b000001000000000000;
export const ForceUpdateForLegacySuspense = /* */ 0b000100000000000000;// Static tags describe aspects of a fiber that are not specific to a render,
// e.g. a fiber uses a passive effect (even if there are no updates on this particular render).
// This enables us to defer more work in the unmount case,
// since we can defer traversing the tree during layout to look for Passive effects,
// and instead rely on the static flag as a signal that there may be cleanup work.
export const PassiveStatic = /*                */ 0b001000000000000000;// Union of side effect groupings as pertains to subtreeFlags
export const BeforeMutationMask = /*           */ 0b000000001100001010;
export const MutationMask = /*                 */ 0b000000010010011110;
export const LayoutMask = /*                   */ 0b000000000010100100;
export const PassiveMask = /*                  */ 0b000000001000001000;// Union of tags that don't get reset on clones.
// This allows certain concepts to persist without recalculting them,
// e.g. whether a subtree contains passive effects or portals.
export const StaticMask = /*                   */ 0b001000000000000000;// These flags allow us to traverse to fibers that have effects on mount
// without traversing the entire tree after every commit for
// double invoking
export const MountLayoutDev = /*               */ 0b010000000000000000;
export const MountPassiveDev = /*              */ 0b100000000000000000;

当然副作用不仅仅只是一个,所以React中在render阶段中采用的是深度遍历的策略去找出当前fiber树中所有的副作用,并维护一个副作用链表EffectList,与链表相关的字段还有firstEffectnextEffectlastEffect 我们来画一张图来简略示意一下。

在这里插入图片描述

解读一下就是,fristEffect指向第一个有副作用的fiber节点,lastEffect指向最后一个具有副作用的fiber节点,中间都是用nextEffect链接,这样组成了一个单向链表。
render阶段里面这一段处理就完了,在后面的commit阶段里面,React会根据EffectList里面fiber节点的副作用,会对应的处理相应的DOM,然后生成无副作用的虚拟节点,进行真实dom的创建。

优先级相关

当然React作为一个庞大的框架,肯定有自己的一套关于渲染的优先级机制,不然全都是一股脑按部就班的走,那肯定不行哒。

那么优先级我们就要关注一下lanealternateReact中每个fiber任务都有自己的lane(执行优先级),这样在render阶段react才知道,应该优先把哪个fiber任务提交到commit阶段去执行。而alternate是在render阶段中用来做为指针的,什么意思?React在状态发生改变的时候,就会根据当前的页面结构,生成两棵fiber树,一棵老的称之为current Fiber,而另一棵将要生成新的页面的树叫做workInProgress Fiber,而alternate作为指针,就是把current Fiber中的每一个节点指向workInProgress Fiber中的每一个节点。同样的他也会从workInProgress Fiber中指向 current Fiber

在这里插入图片描述

我们了解到了alternate,那就来说一说这个lane吧。

// packages/react-reconciler/src/ReactFiberLane.js
export const NoLanes: Lanes = /*                        */ 0b0000000000000000000000000000000;
export const NoLane: Lane = /*                          */ 0b0000000000000000000000000000000;export const SyncLane: Lane = /*                        */ 0b0000000000000000000000000000001;
export const SyncBatchedLane: Lane = /*                 */ 0b0000000000000000000000000000010;export const InputDiscreteHydrationLane: Lane = /*      */ 0b0000000000000000000000000000100;
const InputDiscreteLanes: Lanes = /*                    */ 0b0000000000000000000000000011000;const InputContinuousHydrationLane: Lane = /*           */ 0b0000000000000000000000000100000;
const InputContinuousLanes: Lanes = /*                  */ 0b0000000000000000000000011000000;export const DefaultHydrationLane: Lane = /*            */ 0b0000000000000000000000100000000;
export const DefaultLanes: Lanes = /*                   */ 0b0000000000000000000111000000000;const TransitionHydrationLane: Lane = /*                */ 0b0000000000000000001000000000000;
const TransitionLanes: Lanes = /*                       */ 0b0000000001111111110000000000000;const RetryLanes: Lanes = /*                            */ 0b0000011110000000000000000000000;export const SomeRetryLane: Lanes = /*                  */ 0b0000010000000000000000000000000;export const SelectiveHydrationLane: Lane = /*          */ 0b0000100000000000000000000000000;const NonIdleLanes = /*                                 */ 0b0000111111111111111111111111111;export const IdleHydrationLane: Lane = /*               */ 0b0001000000000000000000000000000;
const IdleLanes: Lanes = /*                             */ 0b0110000000000000000000000000000;export const OffscreenLane: Lane = /*                   */ 0b1000000000000000000000000000000;

可见这个lane也是用31位二进制表示的唯一值,来进行优先级的判定的,并且位数越低,则优先级越大。

Props && State相关

pendingProps: any
本次渲染需要使用的 props 
memoizedProps: any
上次渲染使用的 props 
updateQueue: mixed
用于状态更新、回调函数、DOM更新的队列
memoizedState: any
上次渲染后的 state 状态 
dependencies: Dependencies | null
contexts、events 等依赖

Fiber树的创建与更新的流程

上面一部分讲了React Fiber的基本架构,从真实dom信息副作用优先级等方面看了一下,为后面的render阶段协调调度以及commit阶段打下基础,那么接下来我们去探讨一下new FiberNode之后得到的什么样的rootFiber
我们在第二章节里面提到了整个的创建过程# React源码解析系列(二) – 初始化组件的创建更新流程,那么这里深入探讨一下createFiber,在这个函数里面new FiberNode,创建了rootFiber,他也就是整个React应用的的根fiber。并且在createFiberRoot里面new FiberRootNode,创建了fiberRoot,它便是指向真实dom的根节点。所以在# React源码解析系列(二) – 初始化组件的创建更新流程中我强调了root.currentuninitializedFiber.stateNode这两个东西,也就是这里说的rootFiberstateNode字段指向了 fiberRoot,并且fiberRoot的current指向了rootFiber,具体的示例图如下:

在这里插入图片描述

所以这里就完成了fiber树根节点的创建了。

拿到了上面创建完成的rootFiberfiberRoot之后那么我们接下来就是去根据我们的组件jsx去创建详细的dom树了,举个例子:

<div className='box'><h1 className='title' style={{'color':'red'}}>React源码解析</h1><ul><li>第一章</li><li>第二章</li><li>第三章</li><li>第四章</li></ul>
</div>

现有上面的jsx,那么我们创建dom树的形式是深度优先遍历,已beginworkcompletework表示一个节点的创建过程,流程如下:

在这里插入图片描述

上面的图说明了,在初始化的时候我们的dom树是怎么被创建出来的,那么在状态发生改变的时候,我们会根据当前新的jsx内容创建新的workInProgress fiber,我们以新的jsx为例:

<div className='box'>
<h1 className='title' style={{'color':'red'}}>React源码解析</h1>
+  <h1 className='title' style={{'color':'red'}}>React源码解析系列</h1><ul><li>第一章</li><li>第二章</li><li>第三章</li>
-    <li>第四章</li></ul>
+  <p>总结</p>
</div>

上面的jsx表示,更改了h1的内容,删除了第四章,增加了总结这几个操作,那么react根据当前新的jsx调用createWorkInProgress方法创建workInProgress fiber,那么我们先去看一下createWorkInProgress的源码实现。

export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {let workInProgress = current.alternate;if (workInProgress === null) { // null为初始化,否为update// We use a double buffering pooling technique because we know that we'll// only ever need at most two versions of a tree. We pool the "other" unused// node that we're free to reuse. This is lazily created to avoid allocating// extra objects for things that are never updated. It also allow us to// reclaim the extra memory if needed.workInProgress = createFiber(current.tag,pendingProps,current.key,current.mode,);workInProgress.elementType = current.elementType;workInProgress.type = current.type;workInProgress.stateNode = current.stateNode;if (__DEV__) {// DEV-only fieldsworkInProgress._debugID = current._debugID;workInProgress._debugSource = current._debugSource;workInProgress._debugOwner = current._debugOwner;workInProgress._debugHookTypes = current._debugHookTypes;}// current 指向 workInProgressworkInProgress.alternate = current;// workInProgress 指向 currentcurrent.alternate = workInProgress;} else {// 上一次的propsworkInProgress.pendingProps = pendingProps;// Needed because Blocks store data on type.workInProgress.type = current.type;// We already have an alternate.// Reset the effect tag.//清除flagsworkInProgress.flags = NoFlags;// The effect list is no longer valid.workInProgress.nextEffect = null;workInProgress.firstEffect = null;workInProgress.lastEffect = null;if (enableProfilerTimer) {// We intentionally reset, rather than copy, actualDuration & actualStartTime.// This prevents time from endlessly accumulating in new commits.// This has the downside of resetting values for different priority renders,// But works for yielding (the common case) and should support resuming.workInProgress.actualDuration = 0;workInProgress.actualStartTime = -1;}}// 绑定挂载的子fiber节点优先级、状态、propsworkInProgress.childLanes = current.childLanes;workInProgress.lanes = current.lanes;workInProgress.child = current.child;workInProgress.memoizedProps = current.memoizedProps;workInProgress.memoizedState = current.memoizedState;workInProgress.updateQueue = current.updateQueue;// Clone the dependencies object. This is mutated during the render phase, so// it cannot be shared with the current fiber.const currentDependencies = current.dependencies;workInProgress.dependencies =currentDependencies === null? null: {lanes: currentDependencies.lanes,firstContext: currentDependencies.firstContext,};// These will be overridden during the parent's reconciliationworkInProgress.sibling = current.sibling;workInProgress.index = current.index;workInProgress.ref = current.ref;if (enableProfilerTimer) {workInProgress.selfBaseDuration = current.selfBaseDuration;workInProgress.treeBaseDuration = current.treeBaseDuration;}if (__DEV__) {workInProgress._debugNeedsRemount = current._debugNeedsRemount;switch (workInProgress.tag) {case IndeterminateComponent:case FunctionComponent:case SimpleMemoComponent:workInProgress.type = resolveFunctionForHotReloading(current.type);break;case ClassComponent:workInProgress.type = resolveClassForHotReloading(current.type);break;case ForwardRef:workInProgress.type = resolveForwardRefForHotReloading(current.type);break;default:break;}}return workInProgress;
}

并且为其标记副作用,具体如下:

在这里插入图片描述

而前面所说的alternate在这里相互指向,其实也就是在reconciler阶段起到了复用节点的作用,因为我们所说的current fiber或者是workInProgress fiber都是视图的产物,是可以在"新"与"老"之间转换的。

为什么会出现Fiber架构呢?

相信在座的各位写React的同学出去面试,面试官总会问:”请问你知道React Fiber架构吗?请你说说Fiber架构吧“

为什么会出现?通过上面的React Fiber架构的讲解,我们可以get到几个点,那就是fiber针对每一个fiber节点都会有一套自己的独立的beginworkcompletework,并且能够在每一个具有副作用的节点上进行打标处理,而不是直接变更。而且生成的current fiberworkIProgress fiber可以相互转换,这里间接地可以称之为缓存吧。对比与以前的React应用来讲,以前的React应用是根据执行生命周期diffdom的更新一套流程同步走的,一套流程下来,不能中断,而且每一次的更新都是从根节点出发向下遍历的,我们可以设想一下处理庞大的结构的时候,那将是不可想象的性能开销,处理长时间任务耗时更长,更重要的是用户的交互,事件得不到及时响应,用户体验非常的差。

但是fiber这种结构,我们说的是一种时间分片的概念,通过时间分片把长任务,分成一个个独立的小单元去执行,返回。这样子就不会让js线程React应用独占,能有有空余去处理其他优先级较高的任务,任务得到了相应并且执行,当然了这种情况下页面就不会显得卡顿了。

所以总结来说就是React Fiber给我们提供了一种协调调度暂停中止调优的方式去更好的处理React应用浏览器的工作,保证了页面的性能与流畅度

在这里插入图片描述

总结

这一章讲述了整个的fiber架构与fiber树的创建与更新,那么这里从React应用的初始化挂载到React更新就形成了一部分的闭环完结,之后我们便是沿着流程走到了updateContainer更新这里

相关文章:

react源码中的fiber架构

先看一下FiberNode在源码中的样子 FiberNode // packages/react-reconciler/src/ReactFiber.old.js function FiberNode(tag: WorkTag, pendingProps: mixed, key: null | string, mode: TypeOfMode, ) {// Instancethis.tag tag;this.key key;this.elementType null;t…...

C++类和对象-继承多态

继承 继承是面向对象三大特性之一 定义类时&#xff0c;下级别的成员除了拥有上一级的共性&#xff0c;还有自己的特性&#xff0c;就可以考虑使用继承的技术&#xff0c;减少代码的重复 继承的基本语法 语法&#xff1a;class 子类 : 继承方式 父类 子类也被成为派生类父类…...

appium自动化测试

获取应用包名和入口activity&#xff1a;aapt命令 aapt目录&#xff1a; 安卓sdk的build-tools目录下(如果要在cmd里直接运行&#xff0c;要配置环境变量&#xff0c;否则需要在aapt所在目录下打开cmd) 示例&#xff1a; adt-bundle-windows-x86_64-20140702\sdk\build-too…...

打印流、转换流、数据流 、随机访问流

Java知识点总结&#xff1a;想看的可以从这里进入 目录5、打印流6、转换流7、数据流8、随机访问流5、打印流 实现将基本数据类型的数据格式转化为字符串输出&#xff0c;它们提供了一系列重载的print()和println()方法&#xff0c;用于多种数据类型的输出&#xff0c;这种流不会…...

Java的4种访问权限?

1、public&#xff1a; 所修饰的类、变量、方法&#xff0c;在内外包均具有访问权限&#xff1b;2、protected&#xff1a; 这种权限是为继承而设计的&#xff0c;protected所修饰的成员&#xff0c;对所有子类是可访问的&#xff0c;但只对同包的类是可访问的&#xff0c;对外…...

APP任务模块功能借助php-resque实现业务解耦

先上设计图 说明&#xff1a;任务模块分一次性任务和每日任务&#xff0c;可能还包括男女用户任务区分 处理步骤&#xff1a; 一、同步任务数据库 1.1、任务列表数据库 1.2、完成任务数据库 二、搭建即时消息队列 一、composer require resque/php-resque二、因为服务器red…...

怎么做,才能在职场中晋升?

1 主动原则&#xff1a;主动做事 工作要积极主动&#xff0c;刚进入职场的同学&#xff0c;以为“服从命令听指挥”“领导指哪打哪”就是积极主动&#xff0c;结果易养 1.1 不好习惯 ① 认为主管肯定会帮你搞定晋升 你可能非常信任主管&#xff0c;认为自己只要把主管安排的…...

Vulnhub靶场----2、DC-2

文章目录一、环境搭建二、渗透流程三、思路总结一、环境搭建 DC-2下载地址&#xff1a;https://download.vulnhub.com/dc/DC-2.zip kali&#xff1a;192.168.144.148 DC-2&#xff1a;192.168.144.150 添加hosts文件&#xff1a;192.168.144.150 DC-2 二、渗透流程 nmap -A -…...

Java 基础(3)—synchornized 关键字简单理解

一、synchronized 修饰同步代码块 用 synchronized 修饰代码段作为同步锁&#xff0c;代码如下&#xff1a; public class LockDemo {public Object object new Object();public void show(){synchronized (object) {System.out.println(">>>>>>hell…...

【Linux】调试工具gdb的使用

环境&#xff1a;centos7.6&#xff0c;腾讯云服务器Linux文章都放在了专栏&#xff1a;【Linux】欢迎支持订阅&#x1f339;前言在前文&#xff0c;我们已经讲解了vim工具以及gcc/g的使用&#xff0c;我们可以进行编写代码以及编译代码了&#xff0c;但是还没有学习如何在Linu…...

大数据知识图谱项目——基于知识图谱的医疗知识问答系统(详细讲解及源码)

基于知识图谱的医疗知识问答系统 一、项目概述 本项目基于医疗方面知识的问答&#xff0c;通过搭建一个医疗领域知识图谱&#xff0c;并以该知识图谱完成自动问答与分析服务。本项目以neo4j作为存储&#xff0c;基于传统规则的方式完成了知识问答&#xff0c;并最终以关键词执…...

威马汽车:跃马扬鞭未竟,鞍马劳顿难行?

“活下去&#xff0c;像牲口一样地活下去。” 威马汽车创始人、董事长兼CEO沈晖1月在社交媒体上分享的电影台词&#xff0c;已然成为威马近况的真实写照。 来源&#xff1a;新浪微博威马汽车沈晖Freeman 最近&#xff0c;网上出现了大量关于“威马汽车将实施全员停薪留职”的…...

【网络】网络基础

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【网络】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文章…...

Linux系统之Uboot、Kernel、Busybox思考之三

目录 三 内核的运行 5-中断子系统 6 锁、延迟与原子上下文 7 内存管理子系统 8 驱动的两类框架 三 内核的运行 5-中断子系统 中断子系统的数据结构及设计思想。 中断子系统需要解决中断管理的问题。 如果系统中断较少的话&#xff0c;其管理就不用设计这样一个中断子系统这…...

FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(一)

在最后一个例程中笔者精挑细选了一个较为综合性的项目实战&#xff0c;其中覆盖了很多知识点&#xff0c;也是从一个转产产品中所提炼出来的&#xff0c;所以非常贴近实战项目。 整个工程实现了用户通过对上位机PC端人机界面的操作&#xff0c;即可达到控制豌豆开发并行DAC输出…...

性能测试学习和性能瓶颈分析路线

很多企业招聘都只写性能测试&#xff0c;会使用LR&#xff0c;jmeter工具。其实会使用jmeter和LR进行性能测试还只是性能测试的第一步&#xff0c;离真正的性能测试工程师还很远&#xff0c;笔者也还在路上 .。 性能测试&#xff0c;都是要求测试系统性能&#xff0c;系统自然…...

达梦数据库(DM8)集成使用 Geoserver(2.22.2) 以及其他对应版本详解

达梦数据库&#xff08;DM8&#xff09;集成使用 Geoserver&#xff08;2.22.2&#xff09; 以及其他对应版本详解系统环境版本Geoserver 驱动对应版本达梦 8 集成 Geoserver 过程试错过程问题总结项目需要国产化&#xff0c;选择使用达梦数据库&#xff0c;在技术测试阶段&…...

全开源无加密的RuleApp文章社区APP客户端源码

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 开源无加密的文章社区客户端源码分享 RuleApp文章社区&#xff0c;VIP会员&#xff0c;写作投稿积分商城&#xff0c;付费模块集成&#xff0c;多平台兼容这是一款开源免费&#xff0c;界…...

基于springboot校园二手市场平台

一、项目简介 本项目是一套基于springboot校园二手市场平台&#xff0c;主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目可以直接作为bishe使用。 项目都经过严格调试&#xff0c;确保…...

维度建模基本流程总结

一、维度建模基本流程图数据RD进行业务调研和数据现状调研&#xff0c;产出符合相关模版规范的业务知识文档和数据现状文档。数据PM也会调研相关业务产出需求设计文档&#xff0c;三方参与需求评审&#xff0c;评审通过后基建数据RD进行需求拆解&#xff0c;产出技术方案&#…...

RocketMQ事务消息

RocketMQ事务消息 RocketMq提供的一种高级消息类型&#xff0c;支持在分布式场景下面保障消息生产和本地事务的一致性 生产者将消息发送到服务端服务端将消息持久化成功后&#xff0c;向生产者返回ACK确认消息发送成功&#xff0c;此时消息状态为待投递,这种状态下的消息称之为…...

大数据处理 - 双层桶划分

分桶法简介其实本质上还是分而治之的思想&#xff0c;重在“分”的技巧上&#xff01;适用范围: 第k大&#xff0c;中位数&#xff0c;不重复或重复的数字基本原理及要点: 因为元素范围很大&#xff0c;不能利用直接寻址表&#xff0c;所以通过多次划分&#xff0c;逐步确定范围…...

NFC标签读写器隐私协议

【标签读写器】&#xff08;以下简称“我们”&#xff09;深知个人信息对您的重要性&#xff0c;并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任&#xff0c;恪守以下原则&#xff0c;保护您的个人信息&#xff1a;权责一致原则、目的明确原则、选择同意原…...

DocEE:一种用于文档级事件抽取的大规模细粒度基准 论文解读

DocEE: A Large-Scale and Fine-grained Benchmark for Document-level Event Extraction 论文&#xff1a;NAACL2022.pdf (tongmeihan1995.github.io) 代码&#xff1a;tongmeihan1995/DocEE: DocEE: A Large-Scale and Fine-grained Benchmark for Document-level Event Ext…...

ImageCombiner设计源码详解

前言在前面的博客中介绍了一款Java的海报生成器ImageCombiner,原文地址&#xff1a;拿来就用的Java海报生成器ImageCombiner&#xff08;一&#xff09;&#xff0c;在博文中简单介绍了一下代码以及一个真实的生成案例。但是对源码的介绍不多&#xff0c;本文就针对源码进行深入…...

python基础 | python基础语法

文章目录&#x1f4da;基础语法&#x1f407;输入和输出&#x1f955;print()输出&#x1f955;input()输入&#x1f407; 变量的命名&#x1f407;条件判断&#x1f955;单向判断&#x1f955;双向判断&#x1f955;多向判断&#x1f955;if嵌套&#x1f955;三元表达式&#…...

YOLOv6-3.0-目标检测论文解读

文章目录摘要算法2.1网络设计2.2Anchor辅助训练2.3自蒸馏实验消融实验结论论文&#xff1a; 《YOLOv6 v3.0: A Full-Scale Reloading 》github&#xff1a; https://github.com/meituan/YOLOv6上版本参考 YOLOv6摘要 YOLOv6 v3.0中YOLOv6-N达到37.5AP&#xff0c;1187FPS&…...

JAVA集合之Map >>HashMap/Hashtable/TreeMap/LinkedHashMap结构

Map 是一种键-值对&#xff08;key-value&#xff09;集合&#xff0c;键不可以重复&#xff0c;值可以重复。常见的实现类有&#xff1a;HashMap、Hashtable、TreeMap、LinkedHashMap等。 HashMap&Hashtable HashMap&#xff1a;数据结构为哈希表&#xff0c;允许使用 n…...

JavaScript从零开始 学习记录(一)

前言 选择视频课程之前&#xff0c;不仅查阅了资料&#xff0c;还询问了网友&#xff0c;最终敲定了学习黑马前端的视频教程&#xff0c;学了5小节&#xff0c;发现挺对自己口味的且从反响来看&#xff0c;还是相当不错的&#xff0c;便打算利用这个寒假学完 笔记范围 从这节…...

C++项目——高并发内存池(3)--central cache整体设计

1.central cache的介绍 1.1框架思想 1.1.1哈希映射 centralcache其实也是哈希桶结构的&#xff0c;并且central cache和thread cacha的哈希映射关系是一致的。目的为了&#xff0c;当thread cache某一个哈希桶下没有内存块时&#xff0c;可以利用之前编写的SizeClass::Index…...