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

java面试题-并发关键字(Synchronized,volatile,final)

Synchronized

1.Synchronized可以作用在哪里?

Synchronized可以作用在方法、代码块、静态方法和类上。

方法

public synchronized void method(){//同步代码块
}

代码块

Object lock = new Object();
synchronized(lock){//同步代码块
}

静态方法

public static synchronized void staticMethod(){//同步代码块
}

Class clazz = MyClass.class;
synchronized(clazz){//同步代码块
}

2.Synchronized本质上是通过什么保证线程安全的?

synchronized关键字的底层实现是基于Java对象头(Object Header)和monitor实现的。

每个Java对象在内存中都有一个对象头,用于存储对象的元数据信息,包括对象的哈希码、锁状态标识、GC标记等。当一个线程访问被synchronized修饰的方法或代码块时,它会先尝试获取该对象的monitor(监视器)。

当一个线程成功获取对象的monitor时,该线程就可以进入临界区(Critical Section)执行同步代码块。在进入临界区之前,线程会将对象的锁状态标识设置为“locked”,表示该对象被当前线程占用,其他线程需要等待。当一个线程执行完同步代码块后,它会释放对象的monitor,同时将对象的锁状态标识设置为“unlocked”,这样其他线程就可以继续竞争该对象的锁,进入临界区执行同步代码块。

在Java 5之后,Java引入了基于锁升级的机制,即在Java对象头中添加了一个字段叫做“Mark Word”,用于记录对象的锁状态和其他信息。当一个线程在获取对象锁时,如果发现对象的锁状态是“unlocked”,则它会尝试使用CAS(Compare-And-Swap)指令将对象的锁状态改为“locked”,从而避免使用操作系统级别的互斥量(Mutex)造成的性能开销。如果CAS指令失败,那么就会使用操作系统级别的互斥量来实现锁,这时会将线程阻塞并放入对象的等待队列中。在Java 6之后,JVM还引入了偏向锁和轻量级锁机制,进一步提高了锁的性能。

总之,synchronized关键字的底层实现是基于Java对象头和monitor实现的,通过获取对象的锁来保证线程安全。随着Java虚拟机技术的不断发展,锁机制也在不断优化和升级,以提高并发性能和降低锁的开销。

3.Synchronized使得同时只有一个线程可以执行,性能比较差,有什么提升的方法?

我们可以考虑以下方法:

  1. 减小同步块的范围。尽量减小同步块的范围,只保护必要的共享资源,这样可以缩小锁的粒度,减少线程等待和上下文切换的开销。

  1. 使用局部变量替换共享变量。在多线程环境下,共享变量的访问比局部变量的访问开销更大。如果某个变量只在某个方法或代码块内部使用,那么就可以使用局部变量来代替共享变量,从而减少同步块的范围。

  1. 使用volatile关键字。volatile关键字可以保证变量的可见性和有序性,同时避免了锁的开销,因此可以在一些轻量级的同步场景中使用。

  1. 使用Lock接口。Java提供了Lock接口和其实现类ReentrantLock,可以替代synchronized关键字实现同步,Lock接口提供了更丰富的同步机制,比如支持超时和可中断等操作,同时也允许多个线程同时访问共享资源,从而提高了并发性能。

  1. 使用原子变量。Java提供了一些原子变量类,比如AtomicInteger、AtomicLong、AtomicReference等,这些变量可以实现一些基本的原子操作,避免了锁的开销,从而提高了并发性能。

4.Synchronize有什么样的缺陷? Java Lock是怎么弥补这些缺陷的?

Synchronized作为Java中最基本的同步机制,虽然使用简单,但也存在一些缺陷,主要包括以下几个方面:

  1. 性能问题:Synchronized的性能相对较低,因为它会导致线程之间频繁地竞争锁资源,从而导致上下文切换和线程阻塞等开销,影响程序的并发性能。

  1. 灵活性问题:Synchronized只支持一种锁机制,且不支持可重入、可中断、超时等操作,无法满足一些复杂的同步需求。

  1. 可见性问题:Synchronized只能保证共享变量在锁释放时的可见性,而不能保证变量的实时可见性,因此需要配合volatile关键字等其他机制来使用。

为了弥补Synchronized的这些缺陷,Java提供了Lock接口和其实现类,主要包括ReentrantLock、ReentrantReadWriteLock等。这些类通过以下几个方面来提高并发性能:

  1. 性能优化:Lock实现类可以实现更细粒度的控制,支持更灵活的加锁和解锁操作,可以避免Synchronized的性能问题。

  1. 灵活性提升:Lock接口和实现类提供了更多的同步机制,如可重入锁、读写锁等,同时也支持可中断、超时等操作,能够更好地满足各种复杂的同步需求。

  1. 可见性保障:Lock接口和实现类支持更细粒度的锁定和解锁操作,可以保证共享变量的实时可见性,避免了Synchronized的可见性问题。

  1. 公平性控制:Lock实现类可以通过构造函数参数来控制锁的公平性,从而避免线程饥饿等问题。

需要注意的是,Lock接口和实现类的使用需要手动管理锁的获取和释放,而且需要使用try...finally语句块确保锁的释放,否则可能会导致死锁等问题。此外,Lock的使用也需要注意一些细节问题,如使用tryLock()方法尽量避免死锁、使用ReentrantReadWriteLock来提高读操作的并发性能等。

5.Synchronized和Lock的对比,和选择?

  • Synchronized

使用简单,不需要手动加锁

支持可重入性和线程的可见性锁的释放由JVM自动管理,不容易出现死锁

  • Lock

支持公平锁和非公平锁,更加灵活

支持可中断性,可以避免死锁性能较好,

性能较好,在高并发场景下比Synchronized更快

在选择Synchronized和Lock时,需要根据具体的应用场景和需求进行选择。如果不需要过多的控制锁的粒度,只需要简单的锁定某个对象,那么使用Synchronized是一个不错的选择。如果需要更加灵活的锁控制、更好的性能、更好的可中断性等特性,那么可以选择Lock。同时,在使用Lock时,需要注意避免出现死锁等问题。

6.Synchronized在使用时有何注意事项?

  1. 尽量缩小锁的作用范围;

  1. 避免死锁;

  1. 不要将Synchronized作用于静态变量;

  1. 对锁的释放要及时;

  1. 避免使用String类型作为锁对象;

  1. 尽量避免在同步代码块中执行耗时的操作。

7.Synchronized修饰的方法在抛出异常时,会释放锁吗?

如果在执行Synchronized修饰的方法或代码块时抛出异常,JVM会自动将锁释放掉,以避免死锁的情况。因此,在使用Synchronized时,需要及时释放锁,以避免死锁等问题。

8.synchronized是公平锁吗?

在Java中,Synchronized锁默认情况下是非公平的锁。

9.多个线程等待同一个Synchronized锁的时候,JVM如何选择下一个获取锁的线程?

非公平锁

当有多个线程等待同一个Synchronized锁时,JVM并不会按照线程等待的先后顺序来选择下一个获取锁的线程。相反,它会通过一定的调度算法来选择下一个获取锁的线程,可能会导致某些线程一直无法获取锁,产生饥饿问题。


volatile

1.volatile关键字的作用是什么?

volatile关键字的作用是保证可见性和有序性,即保证所有线程都能看到它的最新值,禁止指令重排序优化,但不能保证原子性。

也就是说,多个线程同时修改同一个volatile变量时,可能会出现并发问题,因此,在需要保证原子性的场合,仍需要使用Synchronized或者Lock等其他机制来进行控制。

2.32位机器上共享的long和double变量的为什么要用volatile?

因为long和double两种数据类型的操作可分为高32位和低32位两部分,因此普通的long或double类型读/写可能不是原子的。

使用volatile关键字可以解决这个问题,因为volatile关键字可以保证变量的可见性和禁止指令重排,即保证一个线程修改了这个变量的值,其他线程可以立即看到这个变量的修改值,而且JVM不会对volatile变量的读写操作进行指令重排序优化,保证操作的有序性。

因此,当多个线程并发读写long和double类型的变量时,可以将其声明为volatile变量,从而保证线程安全。

3.volatile是如何实现可见性的?

volatile关键字可以保证变量的可见性,即一个线程修改了volatile变量的值,其他线程可以立即看到最新的值。实现原理是在写入volatile变量时,使用内存屏障指令将修改后的值刷新回主内存;在读取volatile变量时,使用内存屏障指令从主内存中读取最新的值。

4.volatile是如何实现有序性的?

volatile关键字可以保证变量的有序性,即对一个volatile变量的写操作和读操作都不能重排序。实现原理是在写入volatile变量时,在写操作之前插入内存屏障指令,保证在写操作完成之前,不会重排序到写操作之后的代码;在读取volatile变量时,在读操作之后插入内存屏障指令,保证在读操作完成之后,不会重排序到读操作之前的代码。这样可以保证volatile变量的读写操作按照代码的顺序执行。

5.说下volatile的应用场景?

  1. 状态标记:当一个线程修改了一个共享状态标记时,使用volatile关键字可以确保其他线程能够立即看到最新的状态,从而避免了死锁和饥饿等问题。

public class MyRunnable implements Runnable {private volatile boolean flag = true;@Overridepublic void run() {while (flag) {// do something}}public void stop() {flag = false;}
}
  1. 双重检查锁定(Double Checked Locking):当一个线程要获取一个单例对象时,使用双重检查锁定可以避免多个线程同时创建对象的问题。需要注意的是,双重检查锁定在Java 5之前是不安全的,因为对volatile关键字的实现不够完善。

public class Singleton {private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}
  1. 线程通信:当多个线程之间需要进行通信时,可以使用volatile关键字保证通信的可见性和有序性,从而避免了死锁和饥饿等问题。

6.使用 volatile 必须具备的条件

  1. 变量状态不依赖于先前的状态:如果变量的值取决于先前的状态,那么使用 volatile 不能保证线程安全,需要使用其他的同步手段,如 synchronizedLock

  1. 变量不需要与其他状态变量共同参与不变约束:如果需要多个变量的状态一起满足某个不变条件,那么使用 volatile 也不能保证线程安全,需要使用其他的同步手段。

  1. 对变量的写操作不依赖于当前值:如果对变量的写操作依赖于当前值,那么使用 volatile 不能保证线程安全,需要使用其他的同步手段。

  1. 对变量的访问不需要加锁:如果需要对变量进行复合操作,例如“先检查再更新”操作,那么使用 volatile 不能保证线程安全,需要使用其他的同步手段。


final

1.所有的final修饰的字段都是编译期常量吗?

不是所有使用 final 修饰的字段都是编译期常量。在Java中,final 修饰的字段有两种类型:

  1. 编译期常量:使用 final static 修饰的字段被视为编译期常量,也就是类加载时就被初始化,并且在编译时就能确定其值。这种类型的字段可以直接使用类名进行访问,且访问速度很快,因为它们已经在编译期间被优化了。

  1. 运行期常量:使用 final 修饰的非静态字段被视为运行期常量,这意味着它们在运行时才被初始化,并且它们的值只能被赋值一次。这种类型的字段通常用于不变对象或常量池中的值。

因此,只有使用 final static 修饰的字段才是编译期常量,而不是所有使用 final 修饰的字段。

2.如何理解private所修饰的方法是隐式的final?

在Java中,使用 final 关键字修饰的方法不能被子类重写。如果在父类中使用 private 关键字修饰方法,则子类无法继承该方法,更不可能重写它。因此,对于使用 private 修饰的方法,它们默认就是隐式的 final 方法。

final 关键字的作用是让方法或变量的值在定义后不能被修改。对于私有方法而言,它们只能在本类中被调用,其他类无法调用它们,更不可能修改它们。因此,在这种情况下,使用 final 关键字并没有任何实际作用。

举个例子,假设有以下父类:

public class Parent {private void doSomething() {// ...}
}

如果在子类中定义了一个同名的私有方法:

public class Child extends Parent {private void doSomething() {// ...}
}

则这个子类方法并不是对父类方法的重写,而是一个新定义的私有方法。这意味着,无论父类中的方法是否使用 final 关键字,子类都无法对其进行重写。

3.说说final类型的类如何拓展?

使用 final 修饰的类是不能被继承的,所以不能直接拓展。但是可以使用以下方式来实现拓展:

以下是使用包装器类的示例代码,假设有一个 finalMyFinalClass

public final class MyFinalClass {private final int value;public MyFinalClass(int value) {this.value = value;}public int getValue() {return value;}
}

然后可以创建一个包装器类 MyWrapperClass,并在其中添加一些额外的方法或属性:

public class MyWrapperClass {private final MyFinalClass myFinalClass;public MyWrapperClass(MyFinalClass myFinalClass) {this.myFinalClass = myFinalClass;}public int getValue() {return myFinalClass.getValue();}public String getDescription() {return "This is a wrapper class for MyFinalClass";}
}

可以看到,在 MyWrapperClass 中使用了 MyFinalClass 的实例,并添加了一个 getDescription() 方法来获取包装器类的描述信息。

然后在其他类中,可以使用 MyWrapperClass 来访问 MyFinalClass 的实例,并使用包装器类的额外方法或属性:

MyFinalClass finalInstance = new MyFinalClass(10);
MyWrapperClass wrapperInstance = new MyWrapperClass(finalInstance);
int value = wrapperInstance.getValue(); // 10
String description = wrapperInstance.getDescription(); // "This is a wrapper class for MyFinalClass"

通过这种方式,可以在不继承 MyFinalClass 的情况下,使用包装器类来拓展 MyFinalClass 的功能。

4.final方法可以被重载吗?

是的,final修饰的方法可以被重载,但不能被子类重写。

当子类中声明了一个和父类中同名、同参数列表、同返回类型的方法时,这个方法被称为重载方法。重载方法可以在子类中提供新的实现,但是不能改变父类中 final 方法的行为。

以下是一个示例,其中父类中有一个 final 方法 printMessage(),子类中定义了一个重载方法 printMessage(String message)

public class Parent {public final void printMessage() {System.out.println("Hello, world!");}
}public class Child extends Parent {public void printMessage(String message) {System.out.println("Hello, " + message + "!");}
}

在上面的例子中,Child 类中的 printMessage(String message) 方法是一个重载方法,不会覆盖父类中的 printMessage() 方法。如果尝试在子类中定义一个与父类中的 printMessage() 方法相同的方法,则会编译错误。

5.说说基本类型的final域重排序规则?

在Java语言中,对于基本类型的final域,JVM会禁止对它们的重排序,确保在对象发布之后,该域的值对所有线程可见,因此满足了可见性和有序性。

具体来说,对于final域的写入,JVM会在构造函数执行期间将其初始值写入该域,并将构造函数的return指令之前的所有写操作刷新到主内存中,这样,其他线程在获取该域的值时,就能读到这个最终的值。

同时,由于JVM不允许对final域进行重排序,因此在使用final域时,程序员也不需要担心其可能被重排序从而破坏线程安全。

6.说说final的原理?

在Java中,final关键字可以用来修饰变量、方法和类。对于变量,final保证了变量只被赋值一次,也就是说,final变量的值在赋值后不可更改。这个特性可以通过内存屏障来实现。在写final变量的时候,JVM会在写操作之前插入一个StoreStore屏障,保证该写操作不会被重排到屏障之后。在读final变量的时候,JVM会在读操作之后插入一个LoadLoad屏障,保证该读操作不会被重排到屏障之前。

对于方法和类,final关键字可以用来禁止子类重写方法和继承类。这个特性可以通过在编译期生成类文件时进行优化实现。如果一个类被声明为final,那么编译器会在编译时对该类的所有方法进行静态绑定(static binding),也就是在编译期就确定方法的调用方式,而不需要在运行时进行动态绑定(dynamic binding)。这样,就可以避免在运行时进行虚方法表(virtual method table)的查找,提高程序的执行效率。

总的来说,final的原理是通过内存屏障和编译器优化来实现的,保证了final变量的值只被赋值一次,以及final方法和类的不可更改性和继承性。

相关文章:

java面试题-并发关键字(Synchronized,volatile,final)

Synchronized1.Synchronized可以作用在哪里?Synchronized可以作用在方法、代码块、静态方法和类上。方法public synchronized void method(){//同步代码块 }代码块Object lock new Object(); synchronized(lock){//同步代码块 }静态方法public static synchronized void stat…...

【笔试强训】Day_02

目录 一、选择题 1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 二、编程题 1、排序子序列 2、倒置字符串 一、选择题 1、 使用printf函数打印一个double类型的数据,要求:输出为10进制,输出左对齐30个字符,4位精度。…...

DepGraph:适用任何结构的剪枝

文章目录摘要1、简介2、相关工作3、方法3.1、神经网络中的依赖关系3.2、依赖关系图3.3、使用依赖图剪枝4、实验4.1、设置。4.2、CIFAR的结果4.3、消融实验4.4、适用任何结构剪枝5、结论摘要 论文链接:https://arxiv.org/abs/2301.12900 源码:https://gi…...

【结构体版】通讯录

👦个人主页:Weraphael ✍🏻作者简介:目前是C语言学习者 ✈️专栏:项目 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞&#x…...

Debezium系列之:基于debezium采集数据到kafka,再从kafka将数据流式传输到下游数据库

Debezium系列之:基于debezium采集数据到kafka,再从kafka将数据流式传输到下游数据库 一、需求背景二、准备Debezium集群和相关jar包的详细步骤三、查看插件是否加载成功四、源数据库表结构五、根据源数据库表结构准备目标数据库的表六、基于debezium采集数据到kafka七、查看c…...

【2023】华为OD机试真题Java-题目0217-上班之路

上班之路 题目描述 Jungle生活在美丽的蓝鲸城,大马路都是方方正正,但是每天马路的封闭情况都不一样。 地图由以下元素组成: . — 空地,可以达到;* — 路障,不可达到;S — Jungle的家;T — 公司. 其中我们会限制Jungle拐弯的次数,同时Jungle可以清除给定个数的路障,现在…...

基于spring生态的基础后端开发及渗透测试流程(二)

基于spring生态的基础后端开发及渗透测试流程(二)安全设备IDS蜜罐安全加固渗透测试信息收集子域名域名注册信息企业信息端口扫描源码泄露路径扫描真实ip探测js扫描设备检测蜜罐识别waf识别社工爆破漏洞扫描系统扫描web扫描应急响应继上次写了一份基于spr…...

Python语言零基础入门教程(二十六)

Python OS 文件/目录方法 Python语言零基础入门教程(二十五) 51、Python os.stat_float_times() 方法 概述 os.stat_float_times() 方法用于决定stat_result是否以float对象显示时间戳。 语法 stat_float_times()方法语法格式如下: os.s…...

人们最想看到的是:你在坚持什么?

【人们最想看到的是:你在坚持什么】 长远规划才能对抗不确定性 品牌也能够对抗不确定性 想想这么多年东搞搞,西搞搞 最后缺乏正向积累的【厚度】 趣讲大白话:把每滴水尽量接到碗里 人吃的是饭,拉出来的是信息 *********** 人们在频…...

300行代码手写spring初体验v1.0版本

70%猜想30%验证 spring:IOC 、DI、AOP、MVC MVC作为入口 web.xml 内部依赖一个DispathcheServlet这样一个接口 先来说一下springMVC的一些基础知识 整体的一个思路: 在web.xml里面进行了一个核心servlet的一个配置 核心就是这个DispatcherServlet …...

100天精通Python(数据分析篇)——第76天:Pandas数据类型转换函数pd.to_numeric(参数说明+实战案例)

文章目录专栏导读一、to_numeric参数说明0. 介绍1. arg1)接收列表2)接收一维数组3)接收Series对象2. errors1)errorscoerce2)errors ignore3. downcast1)downcastinteger2)downcastsigned3&…...

链表(超详细--包教包会)

目录 一、概述 二、对链表的基本操作 三、链表的分类 四、静态链表 五、动态链表 1、malloc函数 2、calloc函数 3、free函数 六、动态链表的建立 七、输出链表中的数据 八、查找节点 九、删除节点 十、插入节点 十一、整体代码 一、概述 链表存储结构是一种动态数据…...

爬虫基本知识的认知(爬虫流程 HTTP构建)| 爬虫理论课,附赠三体案例

爬虫是指通过程序自动化地从互联网上获取数据的过程。 基本的爬虫流程可以概括为以下几个步骤: 发送 HTTP 请求:通过 HTTP 协议向指定的 URL 发送请求,获取对应的 HTML 页面。解析 HTML 页面:使用 HTML 解析器对获取的 HTML 页面…...

Ubuntu20.04如何安装虚拟机(并安装Android)

安装虚拟机(KVM)这种KVM只能安装windows无法安装安卓(From https://phoenixnap.com/kb/ubuntu-install-kvm)A type 2 hypervisor enables users to run isolated instances of other operating systems inside a host system. As a Linux based OS, Ubun…...

【腾讯一面】我对我的Java基础不自信了

我对我的Java基础不自信了1、List和set的区别?2、HashSet 是如何保证不重复的3、HashMap是线程安全的吗,为什么不是线程安全的?4、HashMap的扩容过程5、Java获取反射的三种方法6、Redis持久化机制原理7、redis持久化的方式各有哪些优缺点1、L…...

前端都在聊什么 - 第 2 期

Hello 小伙伴们早上、中午、下午、晚上、深夜好,我是爱折腾的 jsliang~「前端都在聊什么」是 jsliang 日常写文章/做视频/玩直播过程中,小伙伴们的提问以及我的解疑整理。本期对应 2023 年的 01.16-01.31 这个时间段。本期针对「规划」「工作」「学习」「…...

每天一道大厂SQL题【Day11】微众银行真题实战(一)

每天一道大厂SQL题【Day11】微众银行真题实战(一) 大家好,我是Maynor。相信大家和我一样,都有一个大厂梦,作为一名资深大数据选手,深知SQL重要性,接下来我准备用100天时间,基于大数据岗面试中的经典SQL题&…...

Cosmos 基础教程(一) -- 不可不知的开发术语

CometBFT DOC 您可以在本节中找到几个技术术语的概述,包括每个术语的解释和进一步资源的链接——在使用Cosmos SDK进行开发时,所有这些都是必不可少的。 在本节中,您将了解以下术语: Cosmos and Interchain LCD RPC Protobuf -协议缓冲…...

JAVA JDK 常用工具类和工具方法

目录 Pair与Triple Lists.partition-将一个大集合分成若干 List集合操作的轮子 对象工具Objects 与ObjectUtils 字符串工具 MapUtils Assert断言 switch语句 三目表达式 IOUtils MultiValueMap MultiMap JAVA各个时间类型的转换(LocalDate与Date类型&a…...

Spring Bean循环依赖

解决SpringBean循环依赖为什么需要3级缓存?回答:1级Map保存单例bean。2级Map 为了保证产生循环引用问题时,每次查询早期引用对象,都拿到同一个对象。3级Map保存ObjectFactory对象。数据结构1级Map singletonObjects2级Map earlySi…...

PHP和Node.js哪个更爽?

先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...