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

Java八股文(Java多线程面试题)

并行和并发的区别?

(1)并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生;

(2)并行是在不同实体上的多个事件,并发是在同一实体上的多个事件;

线程和进程的区别?

进程:是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。

线程:是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。

创建线程的几种方式?

1. 继承Thread类:(1)创建一个继承于Thread类的子类;(2)重写Thread类的run():将此线程要执行的操作声明在run()中;(3)创建子类对象;(4)通过此对象调用start():启动当前线程,调用当前线程的run();

2. 实现Runnable接口:(1)创建一个实现了Runnable接口的类;(2)实现类去重写Runnable中的run()方法;(3)创建实现类的对象;(4)创建Thread类的对象,将实现类的对象作为参数传递到Thread类的构造器中;(5)通过Thread类的对象调用start()。

3. 通过实现Callable接口:(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值。然后再创建Callable实现类的对象;(2)使用FutureTask类来包装Callable对象,FutureTask对象封装了Callable对象的call()方法的返回值;(3)使用FutureTask对象作为Thread对象的target创建并启动新线程;(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

run()和start()有什么区别?

run()方法被称为线程执行体,它的方法体代表了线程需要完成的任务,每个线程都是通过某个特定Thread对象所对应的run()方法来完成操作的。

start()方法用来启动线程。调用start()方法启动线程时,系统会把该run()方法当成线程执行体来处理,这时无需等待run()方法体代码执行完毕,可以直接继续执行下面的代码;这时此线程是处于就绪状态,并没有运行。但如果直接调用线程对象的run()方法,系统把线程对象当成一个普通对象,而run()方法也是一个普通方法,而不是线程执行体。

阻塞线程的方式有哪些?

(1)线程调用sleep()方法主动放弃所占用的处理器资源;(2)线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞;(3)线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有;(4)线程在等待某个通知;(5)程序调用了线程的suspend()方法将该线程挂起。

线程的生命周期

在线程的生命周期中,它要经过新建(New)、就绪(Ready)、运行(Running)、阻塞(Blocked)和死亡(Dead)5种状态。

当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时仅仅由Java虚拟机为其分配内存,并初始化其成员变量的值。

当线程对象调用了start()方法之后,该线程处于就绪状态,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了。至于该线程何时开始运行,取决于JVM里线程调度器的调度。

如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态;当线程数大于处理器数时,会存在多个线程在同一个CPU上轮换的现象。

当一个线程开始运行后,它不可能一直处于运行状态,线程在运行过程中需要被中断,目的是使其他线程获得执行的机会,线程调度的细节取决于底层平台所采用的策略。当发生如下情况时,线程将会进入阻塞状态:(1)线程调用sleep()方法主动放弃所占用的处理器资源;(2)线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞;(3)线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有;(4)线程在等待某个通知;(5)程序调用了线程的suspend()方法将该线程挂起。

当发生如下特定的情况时可以解除上面的阻塞,让该线程重新进入就绪状态:(1)调用sleep()方法的线程经过了指定时间;(2)线程调用的阻塞式IO方法已经返回;(3)线程成功地获得了试图取得的同步监视器;(4)线程正在等待某个通知时,其他线程发出了一个通知;(5)处于挂起状态的线程被调用了resume()恢复方法。

线程会以如下三种方式结束,结束后就处于死亡状态:(1)run()或call()方法执行完成,线程正常结束;(2)线程抛出一个未捕获的Exception或Error;(3)直接调用该线程的stop()方法来结束该线程。

sleep()和wait()的区别?

sleep()方法让正在执行的线程主动让出cpu,然后cpu就可以去执行其他任务,在sleep指定时间后cpu再回到该线程继续往下执行,sleep方法只让出了cpu,而并不会释放同步资源锁,到时间自动恢复。

wait()方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。wait()方法会放弃对象锁,进入等待队列。

sleep()可以在任何地方使用,而wait()只能在同步方法或同步代码块中使用。

sleep()不会释放锁,而wait()会释放锁,并需要通过notify()/notifyAll()重新获取锁。

如何实现子线程先执行,主线程再执行?

启动子线程后,立即调用该线程的join()方法,则主线程必须等待子线程执行完成后再执行。

如何实现线程同步?

(1)使用Synchronized关键字:被该关键字修饰的方法或语句块会自动被加上内置锁,从而实现同步。

(2)使用wait和notify:wait()方法可以让当前线程释放对象锁并进入阻塞状态;notify()方法用于唤醒一个正在等待相应对象锁的线程,使其进入就绪队列,以便在当前线程释放锁后竞争锁,进而得到CPU的执行。

(3)ReentrantLock:ReentrantLock类是可重入、互斥、实现了Lock接口的锁,它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。

(4)使用特殊域变量volatile:volatile关键字为域变量的访问提供了一种免锁机制,使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新。

(5)使用可重入锁实现线程同步;

(6)使用阻塞队列实现线程同步;

wait、notify和notifyAll()?

wait()、notify()、notifyAll()用来实现线程通信,这三个方法都不是Thread类中所声明的方法,而是Object类中声明的方法,并且被final修饰,无法被重写。原因是每个对象都拥有锁,所以让当前线程等待某个对象的锁,所以应该通过这个对象来操作。

wait()方法可以让当前线程释放对象锁并进入阻塞状态。

notify()方法用于唤醒一个正在等待相应对象锁的线程,使其进入就绪队列,以便在当前线程释放锁后竞争锁,进而得到CPU的执行。

notifyAll()用于唤醒所有正在等待相应对象锁的线程,使它们进入就绪队列,以便在当前线程释放锁后竞争锁,进而得到CPU的执行。

每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列。就绪队列存储了已就绪(将要竞争锁)的线程,阻塞队列存储了被阻塞的线程。当一个阻塞线程被唤醒后,才会进入就绪队列,进而等待CPU的调度。反之,当一个线程被wait后,就会进入阻塞队列,等待被唤醒。

synchronized关键字

synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized 关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。

synchronized关键字最主要的三种使用方式:(1)修饰实例方法:对当前对象实例加锁,进入同步代码前要获得当前对象实例的锁;(2)修饰静态方法:对当前类对象加锁,进入同步代码前要获得当前类对象的锁。也就是给当前类加锁,会作用于类的所有对象实例,因为静态成员不属于任何一个实例对象,是类成员。(3)修饰代码块:指定加锁对象,对给定对象加锁,进入同步代码块前要获得给定对象的锁。和synchronized方法一样,synchronized代码块也是锁定当前对象的。

synchronized可以修饰静态方法,但不能修饰静态代码块。

synchronized与Lock的区别

(1)synchronized是Java关键字,在JVM层面实现加锁和解锁;Lock是一个接口,在代码层面实现加锁和解锁。

(2)synchronized可以用在代码块上、方法上;Lock只能写在代码里。

(3)synchronized在代码执行完或出现异常时自动释放锁;Lock不会自动释放锁,需要在finally中显示释放锁。

(4)synchronized会导致线程拿不到锁一直等待;Lock可以设置获取锁失败的超时时间。

(5)synchronized无法得知是否获取锁成功;Lock则可以通过tryLock得知加锁是否成功。

(6)synchronized锁可重入、不可中断、非公平;Lock锁可重入、可中断、可公平/不公平,并可以细分读写锁以提高效率。

synchronized和ReenTrantLock的区别?

synchronized是关键字,依赖于JVM;ReentrantLock是类,依赖于API;它提供了比synchronized更多更灵活的特性:等待可中断、可实现公平锁、可实现选择性通知(锁可以绑定多个条件)。

volatile关键字

volatile关键字是用来保证有序性和可见性的。当一个变量被定义成volatile之后,它将具备两项特性:(1)保证可见性;(2)禁止指令重排。即执行到volatile变量时,其前面的所有语句都执行完,后面所有语句都未执行。且前面语句的结果对volatile变量及其后面语句可见。

虽然volatile能够保证可见性,但它不能保证原子性。volatile变量在各个线程的工作内存中是不存在一致性问题的,但是Java里面的运算操作符并非原子操作,这导致volatile变量的运算在并发下一样是不安全的。

synchronized和volatile的区别?

(1)volatile本质是在告诉JVM当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。

(2)volatile仅能使用在变量级别;synchronized 则可以使用在变量、方法、和类级别的。

(3)volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。

(4)volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。

(5)volatile 标记的变量不会被编译器优化;synchronized 标记的变量可以被编译器优化。

如果不使用synchronized和Lock,如何保证线程安全?

volatile:volatile关键字为域变量的访问提供了一种免锁机制,使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,因此每次使用该域就要重新计算,而不是使用寄存器中的值。

乐观锁和悲观锁

悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。Java中悲观锁是通过synchronized关键字或Lock接口来实现的。

乐观锁:总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁适用于多读的应用类型,这样可以提高吞吐量。乐观锁一般会使用版本号机制或者CAS(Compare And Swap)算法实现。

同步器AQS

抽象队列同步器AbstractQueuedSynchronizer(AQS),用来构建锁或者其他同步组件,减少了各功能组件实现的代码量,也解决了在实现同步器时涉及的大量细节问题,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,例如:ReentrantLock可重入锁(支持公平和非公平的方式获取锁);Semaphore计数信号量;ReentrantReadWriteLock读写锁。

AQS的原理是什么?

如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用 CLH 队列锁实现的,即将暂时获取不到锁的线程加入到队列中。

ThreadLocal

ThreadLocal是线程私有的局部变量存储容器,它用来存储线程私有变量,内部真正存取是一个Map。每个线程可以通过set()和get()存取变量,多线程间无法访问各自的局部变量。只要线程处于活动状态,它所对应的ThreadLocal实例就是可访问的,线程被终止后,它的所有实例将被垃圾收集。ThreadLocal存储的变量属于当前线程。

ThreadLocal经典的使用场景是为每个线程分配一个JDBC连接 Connection,这样就可以保证每个线程的都在各自的Connection上进行数据库的操作。另外ThreadLocal还经常用于管理Session会话,将Session保存在ThreadLocal中,使线程处理多次处理会话时始终是同一个Session。

线程池

系统启动一个新线程的成本是比较高的,在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池。线程池提供了一种限制和管理资源(包括执行一个任务)的方式。

使用线程池的好处:(1)降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗;(2)提高响应速度:当任务到达时,任务可以不需要的等到线程创建就能立即执行;(3)提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

如何创建线程池?

(1)通过ThreadPoolExecutor 的构造方法实现;

(2)通过Executor 框架的工具类 Executors 来实现。

线程池的工作流程

(1)判断核心线程池是否已满,没满则创建一个新的工作线程来执行任务。

(2)判断任务队列是否已满,没满则将新提交的任务添加在工作队列。

(3)判断整个线程池是否已满,没满则创建一个新的工作线程来执行任务,已满则执行饱和(拒绝)策略。

线程池都有哪些状态?

RUNNING:能接受新提交的任务,并且也能处理阻塞队列中的任务。

SHUTDOWN:关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务。在线程池处于 RUNNING 状态时,调用shutdown()方法会使线程池进入到该状态。

STOP:不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。在线程池处于RUNNING或SHUTDOWN状态时,调用shutdownNow()方法会使线程池进入到该状态。

TIDYING:如果所有的任务都已终止了,有效线程数为0,线程池进入该状态后会调用terminated()方法进入TERMINATED 状态。

TERMINATED:在terminated()方法执行完后进入该状态,默认terminated()方法中什么也没有做。

线程池的拒绝策略

当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:(1)AbortPolicy:丢弃任务并抛出异常。(2)DiscardPolicy:丢弃任务,但是不抛出异常。(3)DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复该过程)。(4)CallerRunsPolicy:由调用线程处理该任务。

线程池的队列大小通常怎么设置?

(1)CPU密集型任务:尽量使用较小的线程池,一般为CPU核心数+1。

(2)IO密集型任务:可以使用稍大的线程池,一般为2*CPU核心数。

(63)混合型任务:可以将任务分成IO密集型和CPU密集型任务,然后分别用不同的线程池去处理。只要分完之后两个任务的执行时间相差不大,那么就会比串行执行来的高效。

线程池有哪些参数,各个参数的作用是什么?

(1)corePoolSize(核心工作线程数):当向线程池提交一个任务时,若线程池已创建的线程数小于corePoolSize,即便此时存在空闲线程,也会通过创建一个新线程来执行该任务,直到已创建的线程数大于或等于corePoolSize。

(2)maximumPoolSize(最大线程数):线程池所允许的最大线程个数。当队列满了,且已创建的线程数小于maximumPoolSize,则线程池会创建新的线程来执行任务。另外,对于无界队列,可忽略该参数。

(3)keepAliveTime(多余线程存活时间):当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数。

(4)TimeUnit(线程活动保持时间的单位)

(5)workQueue(队列):用于传输和保存等待执行任务的阻塞队列。

(6)threadFactory(线程创建工厂):用于创建新线程。

(7)handler(拒绝策略):当线程池和队列都满了,再加入线程会执行此策略。

相关文章:

Java八股文(Java多线程面试题)

并行和并发的区别?(1)并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生;(2)并行是在不同实体上的多个事件,并发是在同一实体上的多个事件&#…...

小程序当前页面如何分享别的页面内容呢?

需求分析 因为功能的需要分为两点 他需要调转转发,并且有首页转发点击button按钮进行转发邀请好友帮忙助力,如何做到一个页面多种转发 如何区分,是button转发还剩右上角三个点转发呢? 通过onShareAppMessage()这个函数的事件…...

编写Java哪个编译器好

现在能够编写Java代码的工具简直不要太多,各种各样五花八门,但目前效率最高的还是Intellij Idea。但这个工具对于完全零基础的小白来说,第一次用起来是比较复杂的,因为它的功能太多了。这就好比你要学开车,如果上来就给…...

第十六章 Java为什么使用序列化

为何要指定serialVersionUID的值如果不指定显示serialVersionUID的值,jvm在序列化时会自动生成一个serialVersionUID,跟属性一起序列化,再进行持久化或者网络传输,在反序列化时,jvm会根据属性自动生成一个新版的serial…...

28岁小公司程序员,无车无房不敢结婚,要不要转行?

大家好,这里是程序员晚枫,又来分享程序员的职场故事了~ 今天分享的这位朋友叫小青,我认识他2年多了。以前从事的是土木行业,2年前找我咨询转行程序员的学习路线和职业规划后,通过自学加入了一家创业公司,成…...

出道即封神的ChatGPT,现在怎么样了?

从互联网的普及到智能手机,都让广袤的世界触手而及,如今身在浪潮中的我们,已深知其力。前阵子爆火的ChatGPT,不少人保持观望态度。现如今,国内关于ChatGPT的各大社群讨论,似乎沉寂了不少,现在怎…...

【计算机视觉】CNN 可视化算法

文章目录一、CAM算法1.1 概述1.2 CAM算法介绍二、Grad-CAM算法2.1 概述2.2 Guided Backpropagation2.3 Occlusion Sensitivity2.4 Grad-CAM 整体结构和效果2.5 Grad-CAM 实现细节一、CAM算法 1.1 概述 本文介绍 2016 年提出的 CAM (Class Activation Mapping) 算法&#xff0…...

自动抓取服务器巡检、登录、执行命令记录+备份脚本

文章目录 引抓取【巡检日志】语言&时区设置语言设置时区巡检脚本执行效果抓取【登录信息】登录脚本登录脚本低版本的last命令执行效果抓取【history记录】说明配置history授权日志文件显示时间戳持久化到日志未配置history的配置过history的执行脚本执行脚本...

如何用Python求解微分方程组

文章目录odeint简介示例odeint简介 scipy文档中将odeint函数和ode, comples_ode这两个类称为旧API,是scipy早期使用的微分方程求解器,但由于是Fortran实现的,尽管使用起来并不方便,但速度没得说,所以有的时候还挺推荐…...

【微信小程序】-- 自定义组件 - behaviors(三十九)

💌 所属专栏:【微信小程序开发教程】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &…...

【微信小程序】-- 自定义组件 - 父子组件之间的通信(三十八)

💌 所属专栏:【微信小程序开发教程】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &…...

Java Web 实战 11 - 多线程进阶之常见的锁策略

常见的锁策略常见的锁策略1. 乐观锁 VS 悲观锁2. 普通的互斥锁 VS 读写锁3. 重量级锁 VS 轻量级锁4. 自旋锁 VS 挂起等待锁5. 公平锁 VS 非公平锁6. 可重入锁 vs 不可重入锁7. 常见面试题大家好 , 这篇文章给大家带来的是多线程中常见的锁策略 , 我们会给大家讲解 6 种类别的锁…...

(20)目标检测算法之YOLOv5计算预选框、详解anchor计算

目标检测算法之YOLOv5计算预选框、详解anchor计算 单节段目标检测算法中:预选框的设定直接影响最终的检测精度众所周知,yolov5中采用自适应调整预选框anchor的大小,但万事开头难,配置文件config中的预设还是很重要yolo算法作为on…...

3-1 SpringCloud快速开发入门: Ribbon 是什么

接上一章节Eureka 服务注册中心自我保护机制,这里讲讲Ribbon 是什么 Ribbon 是什么 通常说的负载均衡是指将一个请求均匀地分摊到不同的节点单元上执行,负载均和分为硬件负载均衡和软件负载均衡: **硬件负载均衡:**比如 F5、深信…...

Java【lambda表达式】语法及使用方式介绍

相关文章目录 第一篇: Java【EE初阶】进程相关知识 进程管理 内存管理 文章目录相关文章目录前言一、lambda表达式 是什么?1, lambda表达式 的背景2, 什么是 函数式接口3, lambda表达式 的语法二、lambda表达式 的使用方式1, 无参无返回值2, 有一个参…...

【AcWing】蓝桥杯备赛-深度优先搜索-dfs(2)

目录 写在前面: 题目:94. 递归实现排列型枚举 - AcWing题库 读题: 输入格式: 输出格式: 数据范围: 输入样例: 输出样例: 解题思路: 代码: AC &…...

‘conda‘不是内部或外部命令,也不是可运行的程序或批处理文件。

Anaconda环境搭建常见问题 conda不是内部或外部命令,也不是可运行的程序或批处理文件。 解决方案:配置环境变量 1.找到Anaconda Nvaigator单机右键 2.更多 3.打开文件所在位置 4.继续Anaconda Nvaigator单机右键,更多,选择文件…...

HTTP 3.0来了,UDP取代TCP成为基础协议,TCP究竟输在哪里?

TCP 是 Internet 上使用和部署最广泛的协议之一,多年来一直被视为网络基石,随着HTTP/3正式被标准化,QUIC协议成功“上位”,UDP“取代”TCP成为基础协议,TCP究竟“输”在哪里? HTTP/3 采用了谷歌多年探索的基…...

《JavaCV从入门到实战教程合集》介绍和目录

前言 《JavaCV从入门到实战教程合集》是2016年《JavaCV开发实战教程》和2018年《JavaCV入门教程》2022年《JavaCV音视频实战宝典》三合一汇总合集,完整包含JavaCV入门教程》、《JavaCV开发实战教程》系列和《JavaCV音视频实战宝典》系列所有付费内容。 《JavaCV入…...

Form Generator扩展 文本 组件

一、form-generator是什么?✨ ⭐️ 🌟 form-generator的作者是这样介绍的:Element UI表单设计及代码生成器,可将生成的代码直接运行在基于Element的vue项目中;也可导出JSON表单,使用配套的解析器将JSON解析成真实的表单。 但目前它提供的组件并不能满足我们在项目中的…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...