都工作3年了,怎么能不懂双亲委派呢?(带你手把手断点源码)
💗推荐阅读文章💗
- 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》
- 🌺MySQL系列🌺👉2️⃣《MySQL系列教程》
- 🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》
- 🌻SSM框架系列🌻👉4️⃣《SSM框架系列教程》
🎉本博客知识点收录于🎉👉🚀《JavaSE系列教程》🚀—>✈️18【枚举、类加载器、动态代理】✈️
文章目录
二、类加载器
2.1 类加载时机
我们知道,所有的代码都是运行在内存中的,我们必须把类加载到内存中才能运行;在Java中,所有的Java类都是通过类加载器加载到内存进行执行的;
- 一个类何时被加载?
- 1)main方法所在的类总是被首先初始化
- 2)创建该类对象时,首先会将内加载到内存(如果该类存在父类,那么首先加载父类到内存,创建父类的对象(super))
- 3)访问该类的静态成员时,会将类加载到内存(该静态成员不能被fianl修饰)
- 4)class.forName(“类的全包名”)
package com.dfbz.demo01;
import org.junit.Test;
/*** @author lscl* @version 1.0* @intro:*/
public class Demo01_类何时被加载 {@Testpublic void test1() throws ClassNotFoundException {
// new B(); // 先加载A再加载B
// Integer num = B.num; // 先加载A再加载BClass<?> clazz = Class.forName("com.dfbz.demo01.B"); // 先加载A再加载B}
}
class A {public static Integer num = 10;static {System.out.println("A loader...");}
}
class B extends A {public static Integer num = 20;static {System.out.println("B loader...");}
}
Tips:不管是用什么方法加载,类从始至终只会加载一次;
2.3 类加载器
2.3.1 类加载器的种类
- 启动类加载器Bootstrap ClassLoader: 是嵌在JVM内核中的加载器,该加载器是用C++语言写的,主要负则加载JAVA_HOME/lib下的类库,启动类加载器无法被应用程序直接使用。
- **扩展类加载器Extension ClassLoader:**该加载器器是用JAVA编写,且它的父加载器是Bootstrap,是由sun.misc.Launcher$ExtClassLoader实现的,主要加载JAVA_HOME/lib/ext目录中的类库。开发者可以这几使用扩展类加载器。
- **系统类加载器App ClassLoader:**系统类加载器,也称为应用程序类加载器,负责加载应用程序classpath目录下的所有jar和class文件(第三方jar)。它的父加载器为Ext ClassLoader。
Tips:这里的父加载器并非是Java中的继承关系,而是我们后面学习双亲委派过程中向上委派的加载器,我们将其称为父加载器;
测试类:
package com.dfbz.demo01;
import com.dfbz.demo02.Demo02;
import com.sun.java.accessibility.AccessBridge;
import org.junit.Test;
/*** @author lscl* @version 1.0* @intro:*/
public class Demo02_类加载器的种类 {@Testpublic void test1(){// Bootstrap类加载器是获取不到的,为nullSystem.out.println("Bootstrap ClassLoader: "+ String.class.getClassLoader());// jre\lib\ext\access-bridge-64.jarSystem.out.println("ExtClassLoader ClassLoader: "+ AccessBridge.class.getClassLoader());System.out.println("AppClassLoader ClassLoader: "+ Demo02.class.getClassLoader());}
}
2.3.2 双亲委派机制
从JDK1.2开始,类的加载过程采用双亲委派机制,它是一种任务委派模式。即把加载类的请求交由父加载器处理,一直到顶层的父加载器(BootstrapClassLoader);如果父加载器能加载则用父加载器加载,否则才用子加载器加载该类;
- 示例代码:
package com.dfbz.demo01;
import org.junit.Test;
/*** @author lscl* @version 1.0* @intro:*/
public class Demo03_类加载的过程 {@Testpublic void test1() {Class<T> tClass = T.class;System.out.println(tClass);}class T {}
}
JVM在加载类时,会调用类加载器(ClassLoader)的loadClass方法进行加载;
ClassLoader类加载源码:
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException
{synchronized (getClassLoadingLock(name)) {// 检查该类是否被加载过Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {// 使用父加载器加载c = parent.loadClass(name, false);} else {// 如果没有父加载器则使用BootstrapClassLoader加载c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// 如果依旧没有加载,则调用自身的findClass方法进行加载long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}
}
findClass方法源码:
protected Class<?> findClass(String name) throws ClassNotFoundException {throw new ClassNotFoundException(name);
}
可以看到,默认情况下ClassLoader的findClass方法只是抛出了一个异常而已(这个方法是留给我们写的)
- 双亲委派机制流程图:

- 1)从上图我们可以分析,当一个Demo.class这样的文件要被加载时,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了。


- 2)如果没有加载,那么会拿到父加载器(向上委派),然后调用父加载器的loadClass方法进行加载。AppClassLoader的父加载器为ExtClassLoader,而ExtClassLoader并没有重写loadClass方法,因此还是调用ClassLoader类的loadClass方法,相当于是一个递归的操作;

- 3)父类中同理也会先检查自己是否已经加载过,如果没有再往上。注意是个递归的过程,直到到达Bootstrap classLoader之前,都是在检查是否加载过,并不会选择自己去加载。直到BootstrapClassLoader,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException。

BootstrapClassLoader不能加载该类,因此还是为null,然后调用本类的findClass方法;这里需要注意两点:
- 1)本类还是ExtClassLoader
- 2)ExtClassLoader是自身没有findClass方法,但ExtClassLoader继承与URLClassLoader,并且URLClassLoader提供有findClass方法;

接下来调用到URLClassLoader类中的findClass方法来加载该类:
URLClassLoader类中的findClass方法无法加载我们传递的类,然后向上抛出了一个异常;这里需要注意:
- 1)URLClassLoader类中的findClass方法是通过ExtClassLoader调用findClass方法进去的,因此向上抛出异常后,findClass方法后面的代码将不会执行了,并且触发的异常继续往上抛给调用者(调用loadClass的对象)
- 2)ExtClassLoader的loadClass方法是在AppClassLoader中,通过parent.loadClass()调用进去的,因此异常被抛到了这里;

异常被抛到了AppClassLoader中的loadClass方法中,接着尝试使用AppClassLoader的findClass()方法来加载类;
最终交给AppClassLoader完成类的加载:
2.3.3 双亲委派的好处
我们已经了解了Java中类加载的双亲委派机制,**即加载类时交给父加载器加载,如果父加载器不能加载,再交给子加载器加载;**这样做有何好处呢?
- 1)避免类的重复加载:当父类加载器已经加载了该类时,就没有必要子 ClassLoader 再加载一次。
- 2)安全问题:有了双亲委派机制,当有人想要替换系统级别的类或者篡改他的实现时,在双亲委派机制下,在任何的Java代码运行之前,会将所有要用到的系统类提前使用BootstrapClassLoader加载进内存(而当一个类需要被加载时必定会轮到BootstrapClassLoader来加载,只是是否能加载的问题,不能加载的必定不是系统级别的类),所以其他类加载器并没有机会再去加载,从一定程度上防止了危险代码的植入。
在指定的系统包下建立指定的类(由BootstrapClassLoader、ExtClassLoader加载的系统类):
- Object:
package java.lang;
/*** @author lscl* @version 1.0* @intro:*/
public class Object {static {System.out.println("自定义的Object类被加载了....");}
}
- AccessBridge:
package com.sun.java.accessibility;
/*** @author lscl* @version 1.0* @intro:*/
public class AccessBridge {static {System.out.println("自定义的AccessBridge类被加载了.....");}
}
- 测试类:
package com.dfbz.demo01;
import com.sun.java.accessibility.AccessBridge;
import org.junit.Test;
/*** @author lscl* @version 1.0* @intro:*/
public class Demo04_双亲委派的好处 {@Testpublic void test1() {// java.lang.Object 类在JVM启动时就已经被加载过了,因此不会再被加载了Class<Object> clazz = Object.class;// com.sun.java.accessibility.AccessBridge 类在JVM启动时就已经被加载过了,因此不会再被加载了Class<AccessBridge> accessBridgeClass = AccessBridge.class;}
}
Tips:根据双亲委派机制,我们自定义的Object、AccessBridge类不可能被加载;
另外,JVM的类加载器对包名的定义也有限制;不允许我们自定义系统包名
在系统包名下创建任意一个类:
@Test
public void test2() {// 不允许用户将类定义在受限包名下 ,Prohibited package name: java.langClass<AA> clazz = AA.class;
}
运行结果:
2.3.4 URLClassLoader类加载器
在 java.net 包中,JDK提供了一个更加易用的类加载器URLClassLoader,它扩展了 ClassLoader,能够从本地或者网络上指定的位置加载类,我们可以使用该类作为自定义的类加载器使用。
URLClassLoader的构造方法:
public URLClassLoader(URL[] urls):指定要加载的类所在的URL地址,父类加载器默认为系统类加载器public URLClassLoader(URL[] urls, ClassLoader parent):指定要加载的类所在的URL地址,并指定父类加载器。
1)加载本地磁盘上的类:
在指定目录下准备一个Java文件并把它编译成class文件:
- Show.java:
package com.dfbz.demo01;
/*** @author lscl* @version 1.0* @intro:*/
public class Show {public Show(){System.out.println("new Show....");}
}
- 编译文件:
D:\000\com\dfbz\demo01>javac Show.java
D:\000\com\dfbz\demo01>

- 测试代码:
package com.dfbz.demo01_类加载器的功能;
import org.junit.Test;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
/*** @author lscl* @version 1.0* @intro:*/
public class Demo05_URLClassLoader {@Testpublic void test() throws Exception{File file = new File("D:\\000");// file ---> URIURI uri = file.toURI();// URI ---> URLURL url = uri.toURL();// 根据URL构建一个类加载器URLClassLoader classLoader = new URLClassLoader(new URL[]{url});System.out.println("父类加载器:" + classLoader.getParent()); // 默认父类加载器是系统类加载器Class clazz = classLoader.loadClass("com.dfbz.demo01.Show");// 实例化这个类clazz.newInstance();}
}
运行结果:
2)加载网络上的类:
@Test
public void test2() throws Exception{// 构建一个网络地址URL url = new URL("http://www.baidu.com/class/");URLClassLoader classLoader = new URLClassLoader(new URL[]{url});System.out.println("父类加载器:" + classLoader.getParent()); // 默认父类加载器是系统类加载器Class clazz = classLoader.loadClass("com.baidu.demo.Show");// 实例化这个类clazz.newInstance();
}
Tips:关于加载网络上的类,等我们以后学习了服务器编程再来体验!
2.3.5 自定义类加载器
我们如果需要自定义类加载器,只需要继承ClassLoader,并覆盖掉findClass方法即可。
Tips:我们自定义的类加载器的父加载器为AppClassLoader;
- 自定义类加载器:
package com.dfbz.demo02;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
// 1. 继承 ClassLoader
// 2. 覆盖 findClass方法
public class MyClassLoader extends ClassLoader {// 被加载类所在的目录private String dir;public MyClassLoader(String dir) { // 默认父类加载器就是系统类加载器 AppClassLoaderthis.dir = dir;}public MyClassLoader(ClassLoader parent, String dir) {super(parent);this.dir = dir;}/**** @param name* @return 重写findClass方法* @throws ClassNotFoundException*/@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {try {// 把类名转换为目录 ---> D:/000/com/dfbz/demo01/Show.classString file = dir + "/" + name.replace(".", "/") + ".class";// 从文件中读取这个Class文件InputStream in = new FileInputStream(file);// 构建一个内存输出流(将读取到的Class文件写在内存中)ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buf = new byte[1024];int len ;while ((len = in.read(buf)) != -1) {baos.write(buf, 0, len);}// 读取到的流的二进制数据byte[] data = baos.toByteArray();in.close();baos.close();/*defineClass: 根据类的全包名和内存中的数据流来加载一个类- 参数1: 需要加载类的全包名- 参数2: 已经加载到内存中的数据流- 参数3: 从指定的数据下表开始读取- 参数4: 读取到什么位置*/return defineClass(name, data, 0, data.length);} catch (IOException e) {throw new RuntimeException(e);}}
}
- 测试类:
package com.dfbz.demo02;
/*** @author lscl* @version 1.0* @intro:*/
public class Demo01_自定义类加载器的使用 {public static void main(String[] args) throws Exception{// 创建我们自己的类加载器MyClassLoader classLoader = new MyClassLoader("d:/000");// 使用loadClass加载类Class<?> clazz = classLoader.loadClass("com.dfbz.demo01.Show");clazz.newInstance();}
}
2.3.6 打破双亲委派
我们前面自定义了类加载器,观察下面代码:
package com.dfbz.demo02_自定义类加载器;
/*** @author lscl* @version 1.0* @intro:*/
public class Demo02_打破双亲委派_01 {public static void main(String[] args) throws Exception {MyClassLoader classLoader = new MyClassLoader("d:/000");MyClassLoader classLoader2 = new MyClassLoader("d:/000");Class<?> clazz = classLoader.loadClass("com.dfbz.demo01.Show");Class<?> clazz2 = classLoader2.loadClass("com.dfbz.demo01.Show");System.out.println(clazz == clazz2); // trueSystem.out.println(clazz.getClassLoader()); // sun.misc.Launcher$AppClassLoader@18b4aac2System.out.println(clazz2.getClassLoader()); // sun.misc.Launcher$AppClassLoader@18b4aac2}
}
运行结果:
根据我们之前学习双亲委派机制,上面两个类加载器在加载Show类时,都会判断有没有加载这个类,没有加载则使用父加载器加载,MyClassLoader的父加载器是AppClassLoader,而AppClassLoader正好可以加载这个类;所以其实这两次的加载都是由AppClassLoader来加载的,而AppClassLoader在加载时会判断是否已经加载过,加载过了则不加载;因此Show类只会加载一次;
但是需要注意的是,双亲委派机制的逻辑是写在ClassLoader类的loadClass方法中的,通过一系列逻辑判断最终执行findClass方法来加载类;如果我们加载类直接使用findClass方法呢?那就相当于避开了双亲委派;(当然也可以重写loadClass方法,重新自定义loadClass规则)
- 测试类:
package com.dfbz.demo02;
/*** @author lscl* @version 1.0* @intro:*/
public class Demo03_打破双亲委派_02 {public static void main(String[] args) throws Exception{MyClassLoader classLoader = new MyClassLoader("d:/000");MyClassLoader classLoader2 = new MyClassLoader("d:/000");// 不使用loadClass来加载类,直接使用findClass方法去加载类,每一次调用findClass都相当于是加载一次新的类Class<?> clazz = classLoader.findClass("com.dfbz.demo01.Show");Class<?> clazz2 = classLoader2.findClass("com.dfbz.demo01.Show");System.out.println(clazz == clazz2); // falseSystem.out.println(clazz.getClassLoader()); // com.dfbz.demo02.MyClassLoader@135fbaa4System.out.println(clazz2.getClassLoader()); // com.dfbz.demo02.MyClassLoader@330bedb4}
}
运行结果:
2.2 类的加载过程
2.2.1 类的生命周期
一个Java类从开始到结束整个生命周期会经历7个阶段:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)。
其中验证、准备、解析三个部分又统称为连接(Linking)。
1)加载
加载过程就是把class字节码文件载入到虚拟机中,至于从哪儿加载,虚拟机设计者并没有限定,你可以从文件、压缩包、网络、数据库等等地方加载class字节码。
类加载的方式有:
- 1)通过类的全限定名来获取定义此类的二进制字节流
- 2)将此二进制字节流所代表的静态存储结构转化成方法区的运行时数据结构(加载到内存)
- 3)在内存中生成代表此类的java.lang.Class对象(在堆中),作为该类访问入口;
2)连接
连接阶段的开始,并不一定等到加载阶段结束。加载阶段与连接阶段的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹杂在加载阶段之中的动作任然属于连接阶段,加载和连接这两个阶段的开始顺序是固定的。
- 验证:验证节点主要确保Class文件的格式正确,运行时不会危害JVM的安全;包含文件格式验证、元数据验证、字节码验证、符号引用验证等;
- 准备:准备阶段会为类变量(被static修饰的变量)分配内存并设置类变量的初始值,这些变量所使用的内存都将在方法区中分配。
假如有一个变量private static int value = 123;那么value在准备阶段过后值是0,而不是123;因为这个时候尚未执行任何java方法,而把value赋值为123的动作在初始化阶段才会执行。
但是如果上面的变量被final修饰,变为:private static final int value = 123;编译时javac会为value生成ConstantValue属性,在准备阶段虚拟机就会根据ConstantValue的设置将value赋值为123。 - 解析:解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
Tips:
- 符号引用:在编译的时候每个java类都会被编译成一个class文件,但在编译的时候虚拟机并不知道所引用类的地址,所以就用符号引用来代替,而在这个解析阶段就是为了把这个符号引用转化成为真正的地址的阶段。
- 直接引用:直接引用可以直接指向目标的指针,如果有了直接引用,那引用的目标必定已经在内存中存在。
解析动作主要针对类或接口、字段、类方法、接口方法、方法类型方法句柄和调用点限定符7类符号引用进行。
3)初始化
类初始化是类加载过程的最后一步,这一步会真正开始执行类中定义的Java程序代码(或者说字节码)。在准备阶段,变量已经被赋过一次系统要求的初始值,在初始化阶段,变量会再次赋值为程序员设置的值。比如变量:private static int value = 123;那么value在准备阶段过后值是0,初始化阶段后值是123。
会导致 类加载 的情况
- 1)main方法所在的类总是被首先初始化
- 2)创建该类对象时,首先会将内加载到内存(如果该类存在父类,那么首先加载父类到内存,创建父类的对象(super))
- 3)访问该类的静态成员时,会将类加载到内容(该静态常量不能被final修饰的基本类型和字符型)
- 4)class.forName(“类的全包名”)
不会导致 类加载 的情况
- 1)访问 类的 static final 静态变量(基本类型和字符型)不会触发初始化
- 2)类对象.class 不会触发初始化
- 3)创建该类的数组不会触发初始化
- 4)Class.forName 的参数2 为 false 时
测试类:
package com.dfbz.demo03_类的初始化流程;
/*** @author lscl* @version 1.0* @intro:*/
public class Demo01_测试类 {public static void main(String[] args) {System.out.println(A.B); // 访问类中的final成员类并不会初始化System.out.println(A.OBJ); // 访问非基本数据类型和String时将会初始化AClass<A> aClass = A.class; // 类已经初始化过一次了,并不会再次初始化System.out.println(aClass);}
}
class A {static {System.out.println("A加载了");}public static final String B = "1";
// public static final String B = new String(); // 如果访问的是堆内存中的String,那么A将会被加载public static final Obj OBJ = new Obj();
}
class Obj{}
相关文章:
都工作3年了,怎么能不懂双亲委派呢?(带你手把手断点源码)
💗推荐阅读文章💗 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》🌺MySQL系列🌺👉2️⃣《MySQL系列教程》🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》…...
Hive 运行环境搭建
文章目录Hive 运行环境搭建一、Hive 安装部署1、安装hive2、MySQL 安装3、Hive 元数据配置到 Mysql1) 拷贝驱动2) 配置Metastore 到 MySQL3) 再次启动Hive4) 使用元数据服务的方式访问Hive二、使用Dbaver连接HiveHive 运行环境搭建 HIve 下载地址:http://archive.a…...
SAP ABAP 深度解析Smartform打印特殊符号等功能
ABAP 开发人员可以在 Smartform 输出上显示 SAP 图标或 SAP 符号。例如,需要在 SAP Smart Forms 文档上显示复选框形状的输出。SAP Smartform 文档上可以轻松显示空复选框、标记复选框以及 SAP 图标等特殊符号。 在 SAP Smartform 文档中添加一个新的文本节点。 1. 单击“更…...
React17+React Hook+TS4 最佳实践仿 Jira 企业级项目笔记
前言 个人笔记,记录个人过程,如有不对,敬请指出React17React HookTS4 最佳实践仿 Jira 企业级项目项目完成到第十章,剩下后面就没有看了,说的不是特别好 github地址:https://github.com/superBiuBiuMan/React-jira husky方便我们管理git hooks的工具 REST-API风格 https://zh…...
35- tensorboard的使用 (PyTorch系列) (深度学习)
知识要点 FashionMNIST数据集: 十种产品的分类. # T-shirt/top, Trouser, Pullover, Dress, Coat,Sandal, Shirt, Sneaker, Bag, Ankle Boot.writer SummaryWriter(run/fashion_mnist_experiment_1) # 网站显示一 tensorboard的使用 在网站显示pytorch的架构:1.1 …...
ChatGPT在工业领域的用法
在工业数字化时代,我们需要怎么样的ChatGPT? 近日,ChatGPT热度高居不下,强大的人机交互能力令人咋舌,在国内更是掀起一股讨论热潮。一时间,这场由ChatGPT引起的科技飓风,使得全球最顶尖科技力量…...
使用Chakra-UI封装简书的登录页面组件(React)
要求:使用chakra ui和react 框架将简书的登录页面的表单封装成独立的可重用的组件使用到的API:注册API请求方式:POST 请求地址:https://conduit.productionready.io/api/users请求数据: {"user":{ "username&quo…...
Three.js初试——基础概念(二)
前言 姊妹篇:Three.js初试——基础概念 介绍了 Three.js 的一些核心要素概念,这篇文章会讲一下它的关键要素概念。 之前我们了解到展示一个3D图像,必须要有场景、相机、渲染器这些核心要素,仅仅这些还不够,我们还需要…...
Qt音视频开发21-mpv内核万能属性机制
一、前言 搞过vlc内核后又顺带搞了搞mpv内核,mpv相比vlc,在文件数量、sdk开发便捷性方面绝对占优势的,单文件(可能是静态编译),不像vlc带了一堆插件,通过各种属性来set和get值,后面…...
C语言学生随机抽号演讲计分系统
6.学生随机抽号演讲计分系统(★★★★) 设计一款用于课程大作业检查或比赛计分的软件,基本功能: (1)设置本课程的学生总数 (2)根据本次参与的学生总数,随机抽取一个还未汇报演讲的学生的学号。 (3)每个学生汇报演讲完毕,输入该学生…...
Spring Boot 3.0系列【12】核心特性篇之任务调度
有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot版本3.0.3 源码地址:https://gitee.com/pearl-organization/study-spring-boot3 文章目录 前言Spring Scheduler1. 单线程任务2. 自动配置3. 多线程异步任务Quartz1. 简介2. 核心组件2.1 Job(任务)2.2 Trigger(…...
Java操作XML
Java操作XML XML语法 一个XML文件分为文档声明、元素、属性、注释、CDATA区、特殊字符、处理指令。 转义字符 对于一些单个字符,若想显示其原始样式,也可以使用转义的形式予以处理。 & > & < > < > > > " &g…...
女神节灯笼祝福【HTML+CSS】
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
CUDA并行计算基础知识
1、相关缩写术语 显卡:GPU 显卡驱动:驱动软件 GPU架构: 硬件的设计方式,例如是否有L1 or L2缓存 CUDA: 一种编程语言像C++, Python等,只不过它是专门用来操控GPU的 cudnn: 一个专门为深度学习计算设计的软件库,里面提供了很多专门的计算函数 CUDAToolkit:所谓的装cuda首先…...
88. 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。注意:最终,合并后数组不应…...
卢益贵(码客):软件开发团队的管理要素
卢益贵(码客):软件开发团队的管理要素 最好的范例是领导 无论个人素养、技术水平和代码风格,管理者应该起到典范的作用。 最高的权力是威望 管理者的威望比手中权力更有信服力。在处处倚仗权力施压的团队中,高压必有…...
中小企业的TO B蓝海,如何「掘金」?
中国中小企业的数字化转型土壤,如今究竟成长到了哪一步?对一众数字服务厂商而言,在另一个付费群体出现的当下,产品形态是否应该进行微调? 作者|皮爷 出品|产业家 中国市场存在一个黄金定律:二八法则。 这…...
C++ 算法主题系列之集结0-1背包问题的所有求解方案
1. 前言 背包问题是类型问题,通过对这一类型问题的理解和掌握,从而可以归纳出求解此类问题的思路和模板。 背包问题的分类有: 0-1背包问题,也称为不可分割背包问题。无限背包问题。判定性背包问题.带附属关系的背包问题。双背包…...
【Vue】Vue常见的6种指令
Vue的6种指令-前言指令(Directives)是vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。vue 中的指令按照不同的用途可以分为如下6 大类① 内容渲染指令 ② 属性绑定指令 ③ 事件绑定指令 ④ 双向绑定指令 ⑤ 条件渲染指令 ⑥ …...
计算机科学与技术(嵌入式)四年学习资料_文件目录树
说明: 资料内容主要包括:计嵌专业2019级大学四年主要科目的各种电子资料,有电子实验报告、课程设计报告、课程设计项目、整理复习笔记、电子书、ppt、练习题、期末试卷、部分课程软件资源、科创项目,职业生涯规划书,大…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
