并发编程面试题2

并发编程面试题2

一、AQS高频问题:

1.1 AQS是什么?

AQS就是一个抽象队列同步器,abstract queued sychronizer,本质就是一个抽象类。

AQS中有一个核心属性state,其次还有一个双向链表以及一个单项链表。

首先state是基于volatile修饰,再基于CAS修改,同时可以保证三大特性。(原子,可见,有序)

其次还提供了一个双向链表。有Node对象组成的双向链表。

最后在Condition内部类中,还提供了一个由Node对象组成的单向链表。

AQS是JUC下大量工具的基础类,很多工具都基于AQS实现的,比如lock锁,CountDownLatch,Semaphore,线程池等等都用到了AQS。


state是啥:state就是一个int类型的数值,同步状态,至于到底是什么状态,看子类实现。

condition和单向链表是啥:都知道sync内部提供了wait方法和notify方法的使用,lock锁也需要实现这种机制,lock锁就基于AQS内部的Condition实现了await和signal方法。(对标sync的wait和notify)


sync在线程持有锁时,执行wait方法,会将线程扔到WaitSet等待池中排队,等待唤醒

lcok在线程持有锁时,执行await方法,会将线程封装为Node对象,扔到Condition单向链表中,等待唤醒


Condition在做了什么:将持有锁的线程封装为Node扔到Condition单向链表,同时挂起线程。如果线程唤醒了,就将Condition中的Node扔到AQS的双向链表等待获取锁。

1.2 唤醒线程时,AQS为什么从后往前遍历?

如果线程没有获取到资源,就需要将线程封装为Node对象,安排到AQS的双向链表中排队,并且可能会挂起线程

如果在唤醒线程时,head节点的next是第一个要被唤醒的,如果head的next节点取消了,AQS的逻辑是从tail节点往前遍历,找到离head最近的有效节点?

想解释清楚这个问题,需要先了解,一个Node对象,是如何添加到双向链表中的。

基于addWaiter方法中,是先将当前Node的prev指向tail的节点,再将tail指向我自己,再让prev节点指向我

如下图,如果只执行到了2步骤,此时,Node加入到了AQS队列中,但是从prev节点往后,会找不到当前节点。

image.png

1.3 AQS为什么用双向链表,(为啥不用单向链表)?

因为AQS中,存在取消节点的操作,节点被取消后,需要从AQS的双向链表中断开连接。

还需要保证双向链表的完整性,

  • 需要将prev节点的next指针,指向next节点。
  • 需要将next节点的prev指针,指向prev节点。

如果正常的双向链表,直接操作就可以了。

但是如果是单向链表,需要遍历整个单向链表才能完成的上述的操作。比较浪费资源。

1.4 AQS为什么要有一个虚拟的head节点

有一个哨兵节,点更方便操作。

另一个是因为AQS内部,每个Node都会有一些状态,这个状态不单单针对自己,还针对后续节点

  • 1:当前节点取消了。
  • 0:默认状态,啥事没有。
  • -1:当前节点的后继节点,挂起了。
  • -2:代表当前节点在Condition队列中(await将线程挂起了)
  • -3:代表当前是共享锁,唤醒时,后续节点依然需要被唤醒。

Node节点的ws,表示很多信息,除了当前节点的状态,还会维护后继节点状态。

如果取消虚拟的head节点,一个节点无法同时保存当前阶段状态和后继节点状态。

同时,在释放锁资源时,就要基于head节点的状态是否是-1。来决定是否唤醒后继节点。

如果为-1,正常唤醒

如果不为-1,不需要唤醒吗,减少了一次可能发生的遍历操作,提升性能。

1.5 ReentrantLock的底层实现原理

ReentrantLock是基于AQS实现的。

在线程基于ReentrantLock加锁时,需要基于CAS去修改state属性,如果能从0改为1,代表获取锁资源成功

如果CAS失败了,添加到AQS的双向链表中排队(可能会挂起线程),等待获取锁。

持有锁的线程,如果执行了condition的await方法,线程会封装为Node添加到Condition的单向链表中,等待被唤醒并且重新竞争锁资源

Java中除了一会讲到的线程池中Worker的锁之外,都是可重入锁。

在基础面试题2中,波波老师说到了:Synchronizer和ReentrantLock的区别?

1.6 ReentrantLock的公平锁和非公平锁的区别

注意,想回答的准确些,就别举生活中的列子,用源码的角度去说。

如果用生活中的例子,你就就要用有些人没素质,但是又有素质。

源码:

  • 公平锁和非公平中的lock方法和tryAcquire方法的实现有一内内不同,其他都一样
    • 非公平锁lock:直接尝试将state从 0 ~ 1,如果成功,拿锁直接走,如果失败了,执行tryAcquire
    • 公平锁lock:直接执行tryAcquire
    • 非公平锁tryAcquire:如果当前没有线程持有锁资源,直接再次尝试将state从 0 ~ 1如果成功,拿锁直接走
    • 公平锁tryAcquire:如果当前没有线程持有锁资源,先看一下,有排队的么。
      • 如果没有排队的,直接尝试将state从 0 ~ 1
      • 如果有排队的,第一名不是我,不抢,继续等待。
      • 如果有排队的,我是第一名,直接尝试将state从 0 ~ 1
    • 如果都没拿到锁,公平锁和非公平锁的后续逻辑是一样的,排队后,就不存在所谓的插队。

生活的例子:非公平锁会有机会尝试强行获取锁资源两次,成功开开心心走人,失败,消消停停去排队。

  • 有个人前来做核酸
    • 公平锁:先看眼,有排队的么,有就去排队
    • 非公平锁:不管什么情况,先尝试做凳子上。如果坐上了,直接被扣,扣完走人,如果没做到凳子上
      • 有人正在扣嗓子眼么?
        • 没人正在被扣,上去尝试做凳子上!成功了,扣完走人。
        • 如果有人正在扣,消停去排队。

1.7 ReentrantReadWriteLock如何实现的读写锁

如果一个操作写少读多,还用互斥锁的话,性能太低,因为读读不存在并发问题。

怎么解决啊,有读写锁的出现。

ReentrantReadWriteLock也是基于AQS实现的一个读写锁,但是锁资源用state标识。

如何基于一个int来标识两个锁信息,有写锁,有读锁,怎么做的?

一个int,占了32个bit位。

在写锁获取锁时,基于CAS修改state的低16位的值。

在读锁获取锁时,基于CAS修改state的高16位的值。

写锁的重入,基于state低16直接标识,因为写锁是互斥的。

读锁的重入,无法基于state的高16位去标识,因为读锁是共享的,可以多个线程同时持有。所以读锁的重入用的是ThreadLocal来表示,同时也会对state的高16为进行追加。

二、阻塞队列高频问题:

2.1 说下你熟悉的阻塞队列?

ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue

ArrayBlockingQueue:底层基于数组实现,记得new的时候设置好边界。

LinkedBlockingQueue:底层基于链表实现的,可以认为是无界队列,但是可以设置长度。

PriorityBlockingQueue:底层是基于数组实现的二叉堆,可以认为是无界队列,因为数组会扩容。

ArrayBlockingQueue,LinkedBlockingQueue是ThreadPoolExecutor线程池最常用的两个阻塞队列。

PriorityBlockingQueue:是ScheduleThreadPoolExecutor定时任务线程池用的阻塞队列跟PriorityBlockingQueue的底层实现是一样的。(其实本质用的是DelayWorkQueue)

2.2 虚假唤醒是什么?

虚假唤醒在阻塞队列的源码中就有体现。

比如消费者1在消费数据时,会先判断队列是否有元素,如果元素个数为0,消费者1会挂起。

此处判断元素为0的位置,如果用if循环会导致出现一个问题。

如果生产者添加了一个数据,会唤醒消费者1。

但是如果消费者1没拿到锁资源,消费者2拿到了锁资源并带走了数据的话。

消费者1再次拿到锁资源时,无法从队列获取到任何元素。导致出现逻辑问题。

解决方案,将判断元素个数的位置,设置为while判断。

三、线程池高频问题:(最重要的点)

3.1 线程池的7个参数(不会就回家等通知)

核心线程数,最大线程数,最大空闲时间,时间单位,阻塞队列,线程工厂,拒绝策略

3.2 线程池的状态有什么,如何记录的?

线程池不是什么时候都接活的!

线程池有5个状态。、

image.png

线程池的状态是在ctl属性中记录的。本质就是int类型

image.png

ctl的高三位记录线程池状态

低29位,记录工作线程个数。即便你指定的线程最大数量是Integer.MAX_VALUE他也到不了

3.3 线程池常见的拒绝策略(不会就回家等通知)

AbortPolicy:抛异常(默认)

image.png

CallerRunsPolicy,谁提交的任务,谁执行。异步变同步

image.png

DiscardPolicy:任务直接不要

image.png

DiscardOldestPolicy:把最早放过来的任务丢失,再次尝试将当前任务交给线程池处理

image.png

一般情况下,线程池自带的无法满足业务时,自定义一个线程池的拒绝策略。

实现下面的接口即可。

image.png

3.4 线程池执行流程(不会就回家等通知)

核心线程不是new完就构建的,是懒加载的机制,添加任务才会构建核心线程

2个核心线程 5个最大线程 阻塞队列长度为2

image.png

3.5 线程池为什么添加空任务的非核心线程

image.png

避免线程池出现工作队列有任务,但是没有工作线程处理。

线程池可以设置核心线程数是0个。这样,任务扔到阻塞队列,但是没有工作线程,这不凉凉了么~~

线程池中的核心线程不是一定不会被回收,线程池中有一个属性,如果设置为true,核心线程也会被干掉

image.png

3.6 在没任务时,线程池中的工作线程在干嘛?

线程会挂起,默认核心线程是WAITING状态,非核心是TIMED_WAITING

如果是核心线程,默认情况下,会在阻塞队列的位置执行take方法,直到拿到任务为止。

如果是非核心线程,默认情况下,会在阻塞队列的位置执行poll方法,等待最大空闲时间,如果没任务,直接拉走咔嚓掉,如果有活,那就正常干。

3.7 工作线程出现异常会导致什么问题?

是否抛出异常、影响其他线程吗、工作线程会嘎嘛?

如果任务是execute方法执行的,工作线程会将异常抛出。

如果任务是submit方法执行的futureTask,工作线程会将异常捕获并保存到FutureTask里,可以基于futureTask的get得到异常信息

出现异常的工作线程不会影响到其他的工作线程。

runWorker中的异常会被抛到run方法中,run方法会异常结束,run方法结束,线程就嘎了!

如果是submit,异常没抛出来,那就不嘎~

3.8 工作线程继承AQS的目的是什么?

工作线程的本质,就是Worker对象

继承AQS跟shutdown和shutdownNow有关系。

如果是shutdown,会中断空闲的工作线程,基于Worker实现的AQS中的state的值来判断能否中断工作线程。

如果工作线程的state是0,代表空闲,可以中断,如果是1,代表正在干活。

如果是shutdownNow,直接强制中断所有工作线程

3.9 核心参数怎么设置?

如果面试问到,你项目中的线程池参数设置的是多少,你先给个准确的数字和配置。别上来就说怎么设置!!

线程池的目的是为了充分发挥CPU的资源。提升整个系统的性能。

系统内部不同业务的线程池参考的方式也不一样。

如果是CPU密集的任务,一般也就是CPU内核数 + 1的核心线程数。这样足以充分发挥CPU性能。

如果是IO密集的任务,因为IO的程度不一样的啊,有的是1s,有的是1ms,有的是1分钟,所以IO密集的任务在用线程池处理时,一定要通过压测的方式,观察CPU资源的占用情况,来决定核心线程数。一般发挥CPU性能到70~80足矣。所以线程池的参数设置需要通过压测以及多次调整才能得出具体的。

比如一个业务要查询三个服务

并发编程面试题3

一、CountDownLatch,Semaphore的高频问题:

1.1 CountDownLatch是啥?有啥用?底层咋实现的?(可以融入到你的项目业务中。)

CountDownLatch本质其实就是一个计数器。

在多线程并形处理业务时,需要等待其他线程处理完,再做后续的合并等操作,再响应用户时,可以使用CountDownLatch做计数,等到其他线程出现完之后,主线程就会被唤醒。

CountDownLatch本身就是基于AQS实现的。

new CountDownLatch时,直接指定好具体的数值。这个数值会复制给state属性。

当子线程处理完任务后,执行countDown方法,内部就是直接给state - 1而已。

当state减为0之后,执行await挂起的线程,就会被唤醒。

CountDownLatch不能重复使用,用完就凉凉。

1.2 Semaphore是啥?有啥用?底层咋实现的?

信号量,就是一个可以用于做限流功能的工具类。

比如Hystrix中涉及到了信号量隔离,要求并发的线程数有限制,就可以使用信号量实现。

比如要求当前服务最多10个线程同时干活,将信号量设置为10。没一个任务提交都需要获取一个信号量,就去干活,干完了,归还信号量。

信号量也是基于AQS实现的。

构建信号量时,指定信号量资源数,获取时,指定获取几个信号量,也是CAS保证原子性,归还也是类似的。

1.3 main线程结束,程序会停止嘛?

如果main线程结束,但是还有用户线程在执行,不会结束!

如果main线程结束,剩下的都是守护线程,结束!

二、CopyOnWriteArrayList的高频问题:

2.1 CopyOnWriteArrayList是如何保证线程安全的?有什么缺点吗?

CopyOnWriteArrayList写数据时,是基于ReentrantLock保证原子性的。

其次,写数据时,会复制一个副本写入,写入成功后,才会写入到CopyOnWriteArrayList中的数组。

保证读数据时,不要出现数据不一致的问题。

如果数据量比较大时,每次写入数据,都需要复制一个副本,对空间的占用太大了。如果数据量比较大,不推荐使用CopyOnWriteArrayList。

写操作要求保证原子性,读操作保证并发,并且数据量不大 ~

三、ConcurrentHashMap(JDK1.8)的高频问题:

3.1 HashMap为啥线程不安全?

问题1:JDK1.7里有环(扩容时)。

问题2:数据会覆盖,数据可能丢失。

问题3:其次计数器,也是传统的++,在记录元素个数和HashMap写的次数时,记录不准确。

问题4:数据迁移,扩容,也可能会丢失数据。

3.2 ConcurrentHashMap如何保证线程安全的?

回答1:尾插,其次扩容有CAS保证线程安全

回答2:写入数组时,基于CAS保证安全,挂入链表或插入红黑树时,基于synchronized保证安全。

回答3:这里ConcurrentHashMap是采用LongAdder实现的技术,底层还是CAS。(AtomicLong)

回答4:ConcurrentHashMap扩容时,一点基于CAS保证数据迁移不出现并发问题, 其次ConcurrentHashMap还提供了并发扩容的操作。举个例子,数组长度64扩容为128,两个线程同时扩容的话,

线程A领取64-48索引的数据迁移任务,线程B领取47-32的索引数据迁移任务。关键是领取任务时,是基于CAS保证线程安全的。

3.3 ConcurrentHashMap构建好,数组就创建出来了吗?如果不是,如何保证初始化数组的线程安全?

ConcurrentHashMap是懒加载的机制,而且大多数的框架组件都是懒加载的~

基于CAS来保证初始化线程安全的,这里不但涉及到了CAS去修改sizeCtl的变量去控制线程初始化数据的原子性,同时还使用了DCL,外层判断数组未初始化,中间基于CAS修改sizeCtl,内层再做数组未初始化判断。

image.png

3.4 为什么负载因子是0.75,为什么链表长度到8转为红黑树?

而且ConcurrentHashMap的负载因子不允许修改!

负载因子是0.75从两个方面去解释。

为啥不是0.5,为啥不是1?

0.5:如果负载因子是0.5,数据添加一半就开始扩容了

  • 优点:hash碰撞少,查询效率高。
  • 缺点:扩容太频繁,而且空间利用率低。

1:如果负载因子是1,数据添加到数组长度才开始扩容

  • 优点:扩容不频繁,空间利用率可以的。
  • 缺点:hash冲突会特别频繁,数据挂到链表上,影响查询效率,甚至链表过长生成红黑树,导致写入的效率也收到影响。

0.75就可以说是一个居中的选择,两个方面都兼顾了。

再聊就是泊松分布,在负载因子是0.75时,根据泊松分布得出,链表长度达到8的概率是非常低的,源码中的标识是0.00000006,生成红黑树的概率特别低。

虽然ConcurrentHashMap引入了红黑树,但是红黑树对于写入的维护成本更高,能不用就不用,HashMap源码的注释也描述了,要尽可能规避红黑树。

至于6退化为链表,是因为满树是7个值,7不退化是为了防止频繁的链表和红黑树转换,这里6退化留下了一个中间值,避免频繁的转换。

put操作太频繁的场景,会造成扩容时期put的阻塞 ?

一般情况下不会造成阻塞。

因为如果在put操作时,发现当前索引位置并没有数据时,正常把数据落到老数组上。

如果put操作时,发现当前位置数据已经被迁移到了新数组,这时无法正常插入,去帮助扩容,快速结束扩容操作,并且重新选择索引位置查询

3.5 ConcurrentHashMap何时扩容,扩容的流程是什么?

  • ConcurrentHashMap中的元素个数,达到了负载因子计算的阈值,那么直接扩容
  • 当调用putAll方法,查询大量数据时,也可能会造成直接扩容的操作,大量数据是如果插入的数据大于下次扩容的阈值,直接扩容,然后再插入
  • 数组长度小于64,并且链表长度大于等于8时,会触发扩容image.png

扩容的流程:(sizeCtl是一个int类型变量,用于控制初始化和扩容)

  • 每个扩容的线程都需要基于oldTable的长度计算一个扩容标识戳(避免出现两个扩容线程的数组长度不一致。其次保证扩容标识戳的16位是1,这样左移16位会得到一个负数)
  • 第一个扩容的线程,会对sizeCtl + 2,代表当前有1个线程来扩容
  • 除去第一个扩容的线程,其他线程会对sizeCtl + 1,代表现在又来了一个线程帮助扩容
  • 第一个线程会初始化新数组。
  • 每个线程会领取迁移数据的任务,将oldTable中的数据迁移到newTable。默认情况下,每个线程每次领取长度为16的迁移数据任务
  • 当数据迁移完毕时,每个线程再去领取任务时,发现没任务可领了,退出扩容,对sizeCtl - 1。
  • 最后一个退出扩容的线程,发现-1之后,还剩1,最后一个退出扩容的线程会从头到尾再检查一次,有没有遗留的数据没有迁移走(这种情况基本不发生),检查完之后,再-1,这样sizeCtl扣除完,扩容结束。

3.6 ConcurrentHashMap得计数器如何实现的?

这里是基于LongAdder的机制实现,但是并没有直接用LongAdder的引用,而是根据LongAdder的原理写了一个相似度在80%以上的代码,直接使用。

LongAdder使用CAS添加,保证原子性,其次基于分段锁,保证并发性。

3.7 ConcurrentHashMap的读操作会阻塞嘛?

无论查哪,都不阻塞。

查询数组? :第一块就是查看元素是否在数组,在就直接返回。

查询链表?:第二块,如果没特殊情况,就在链表next,next查询即可。

扩容时?:第三块,如果当前索引位置是-1,代表当前位置数据全部都迁移到了新数组,直接去新数组查询,不管有没有扩容完。

查询红黑树?:如果有一个线程正在写入红黑树,此时读线程还能去红黑树查询吗?因为红黑树为了保证平衡可能会旋转,旋转会换指针,可能会出现问题。所以在转换红黑树时,不但有一个红黑树,还会保留一个双向链表,此时会查询双向链表,不让读线程阻塞。至于如何判断是否有线程在写,和等待写或者是读红黑树,根据TreeBin的lockState来判断,如果是1,代表有线程正在写,如果为2,代表有写线程等待写,如果是4n,代表有多个线程在做读操作。

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

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

相关文章

【Ubuntu】安装docker,docker compose 以及部署一个docker应用

大家好!在过去,已经分享了很多有关通过Docker部署应用的内容。今天,我将为大家详细介绍如何在Ubuntu系统上部署最新的Docker平台。 Docker是什么 Docker是一个开源的容器化平台,它允许您将应用程序及其所有依赖项打包到称为容器…

CH343 USB转串口芯片资料下载(合集)

1、产品手册 CH343DS1.PDF - 南京沁恒微电子股份有限公司CH343技术手册,USB转单串口芯片,支持最高6M波特率,串口信号支持1.8~5V,内置晶振。CH343使用系统集成的CDC驱动或厂商驱动。厂商驱动支持完整串口功能和更高波特率。https:…

基于STM32微控制器的物联网(IoT)节点设计与实现

基于STM32微控制器的物联网(IoT)节点的设计和实现。我们讨论物联网节点的基本概念和功能,并详细介绍了STM32微控制器的特点和优势。然后,我们将探讨如何使用STM32开发环境和相关的硬件模块来设计和实现一个完整的物联网节点。最后,我们将提供一个示例代码,展示如何在STM3…

【24择校指南】南京大学计算机考研考情分析

南京大学(A) 考研难度(☆☆☆☆☆) 内容:23考情概况(拟录取和复试分数人数统计)、院校概况、23初试科目、23复试详情、参考书目、各科目考情分析、各专业考情分析。 正文2178字,预计阅读:6分…

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架

简单手写SpringIOC框架 环境搭建基于XML方式项目结构项目代码运行结果 基于注解方式项目结构项目代码运行结果 简单手写SpringIOC框架核心原理基于XML方式原理项目结构项目代码运行结果 基于注解方式原理项目结构项目代码运行结果 环境搭建 基于XML方式 项目结构 项目代码 p…

JSP实训项目设计报告—MVC简易购物商城

JSP实训项目设计报告—MVC简易购物商城 文章目录 JSP实训项目设计报告—MVC简易购物商城设计目的设计要求设计思路系统要求单点登录模块商品展示模块购物车展示模块 概要设计Model层View层Controller层 详细设计Model层View层登录界面系统主界面 Controller层 系统运行效果项目…

kafka是有序的吗?如何保证有序?

首先,Kafka无法保证消息的全局有序性,这是因为Kafka的设计中允许多个生产者并行地向同一个主题写入消息。而且,一个主题可能会被划分为多个分区,每个分区都可以在独立的生产者和消费者之间进行并行处理。因此,生产者将…

【MongoDB】数据库、集合、文档常用CRUD命令

目录 一、数据库操作 1、创建数据库操作 2、查看当前有哪些数据库 3、查看当前在使用哪个数据库 4、删除数据库 二、集合操作 1、查看有哪些集合 2、删除集合 3、创建集合 三、文档基本操作 1、插入数据 2、查询数据 3、删除数据 4、修改数据 四、文档分页查询 …

CSP复习每日一题(四)

树的重心 给定一颗树,树中包含 n n n 个结点(编号 1 ∼ n 1∼n 1∼n)和 n − 1 n−1 n−1条无向边。请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。 重心定义: 重心是指树中的一…

试图将更改推送到 GitHub,但是远程仓库已经包含了您本地没有的工作(可能是其他人提交的修改)

这通常是由于其他人或其他仓库推送到了相同的分支上,导致您的本地仓库和远程仓库之间存在冲突。 错误信息: To github.com:8upersaiyan/CKmuduo.git ! [rejected] main -> main (fetch first) error: failed to push some refs to github.com:8upers…

元宇宙时代来临,AI数字人的应用方式有哪些?

在数字化背景下,元宇宙的时代已经来临,当你看到网络新闻上各形各色的虚拟数字人时,你是不是也有些都心动呢?与真人相比,AI虚拟数字人还具有成本低廉并且不受时间、空间限制的特点,数字人的使用场景正在逐渐…

React集成tinymce插件

目录 一、Tinymce介绍 二、React集成Tinymce 1、安装tinymce/tinymce-react组件 2、React中引用 三、如何配置中文语言包 1、下载中文包 2、把语言文件放入tinymce 3、tinymce配置项中配置语言 一、Tinymce介绍 官网:The Most Advanced WYSIWYG Editor | T…

【脚踢数据结构】深入理解栈

(꒪ꇴ꒪ ),Hello我是祐言QAQ我的博客主页:C/C语言,Linux基础,ARM开发板,软件配置等领域博主🌍快上🚘,一起学习,让我们成为一个强大的攻城狮!送给自己和读者的一句鸡汤🤔&…

数据清理在数据科学中的重要性

什么是数据清理? 推荐:使用 NSDT场景编辑器 助你快速搭建可编辑的3D应用场景 在数据科学中,数据清理是识别不正确数据并修复错误的过程,以便最终数据集可供使用。错误可能包括重复字段、格式不正确、字段不完整、数据不相关或不准…

web集群学习:源码安装nginx配置启动服务脚本、IP、端口、域名的虚拟主机

目录 1、源码安装nginx,并提供服务脚本。 2、配置基于ip地址的虚拟主机 3、配置基于端口的虚拟主机 4、配置基于域名的虚拟主机 1、源码安装nginx,并提供服务脚本。 1、源码安装会有一些软件依赖 (1)检查并安装 Nginx 基础依赖…

数据结构刷题训练——链表篇(二)

目录 前言 1.题目一:链表分割 1.1 思路 1.2 分析 1.3 题解 2. 题目二:相交链表 2.1 思路 2.2 分析 2.3 题解 3. 题目三:环形链表 3.1 思路 3.2 分析 3.3 题解 总结 前言 本期继续分享链表相关的OJ题目,在这个专栏博客…

【论文阅读】EULER:通过可扩展时间链接预测检测网络横向移动(NDSS-2022)

作者:乔治华盛顿大学-Isaiah J. King、H. Howie Huang 引用:King I J, Huang H H. Euler: Detecting Network Lateral Movement via Scalable Temporal Graph Link Prediction [C]. Proceedings 2022 Network and Distributed System Security Symposium…

UDP通信实验、广播与组播、本地套接字

文章目录 流程函数应用广播应用 组播(多播)本地套接字应用 流程 函数 返回值: 成功,返回成功发送的数据长度 失败,-1 返回值: 成功,返回成功接收数据长度 失败,-1 应用 广播 应用 …

MongoDB文档-进阶使用-MongoDB索引-createindex()与dropindex()-在MongoDB中使用正则表达式来查找

阿丹: 之前研究了MongoDB的基础增删改查。在学会基础的数据库增删改查肯定是不够的。这个时候就涉及到了数据库搜索的时候的效率。需要提高数据的搜索效率。 MongoDB索引 在所以数据库中如果没有数据索引的时候。如果需要查找到一些数据。都会去主动扫描所有可能存…

mybatis-plus的逻辑删除的坑

一旦在逻辑字段上加了TableLogic逻辑删除的配置,并且使用mybatis-plus自带的方法时(如果自己用xml写SQL不会出现下面的情况) 查询、修改时会自动排除逻辑删除的数据 当使用mybatis-plus自带的查询方法时,就不用每次查询的时候跟…