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

JavaWeb14-线程池

目录

1.传统线程的缺点

2.线程池的定义

3.线程池的优点

4.线程池的创建/使用(2类7种)

4.1.通过Executors(执行器)自动创建(6种)

①Executors.newFixedThreadPool:创建⼀个固定⼤⼩的线程池,可控制并发的线程数,超出的线程会在队列中等待。

--->PS:submit VS execute

--->PS:有返回值的线程池实现

--->PS:线程池中的线程工厂

②Executors.newCachedThreadPool:创建⼀个可缓存的线程池,若线程数超过处理所需,缓存⼀段时间后会回收,若线程数量不够,则新建线程,线程数随任务量而定(前提CPU性能好)。

③Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执⾏顺序。

--->PS:(常见面试题)newSingleThreadExecutor:创建单个线程数的线程池,那为何不直接使用线程?单线程线程池的意义?

④Executors.newScheduledThreadPool:创建⼀个可以执⾏延迟任务的线程池。

--->a.延迟执行一次

--->b.固定频率执行scheduleAtFixedRate

--->c.固定频率执行scheduleWithFixedDelay

 --->PS:scheduleAtFixedRate VS scheduleWithFixedDelay

⑤Executors.newSingleThreadScheduledExecutor:创建⼀个单线程的可以执行延迟任务的线程池。

⑥Executors.newWorkStealingPool:根据当前服务器的CPU创建⼀个抢占式执⾏的线程池(任务执⾏顺序不确定)【JDK 1.8 添加】。

4.2.通过ThreadPoolExecutor手动创建(1种)

⑦ThreadPoolExecutor:重点掌握,最原始方式,推荐使用。

--->Executors自动创建线程池返回的线程池对象的弊端如下:

--->a.ThreadPoolExecutor 参数说明(包含 7 个参数可供设置,最少需要设置5个参数)

--->b.线程池执行流程

--->c.线程池拒绝策略(4【JDK提供】+1【自定义】)

5.线程池状态(5种)

①RUNNING:

②SHUTDOWN:

③STOP:

④TIDYING:

⑤TERMINATED:

a.各个状态的转换过程

b.shutdown VS shutdownNow

6.究竟选用哪种线程池?


1.传统线程的缺点

  • 有任务时创建线程,没任务时结束线程:创建线程需要开辟本地线程栈、虚拟机栈、程序计数器等私有线程内存,消耗的时候也需要释放这些内存。频繁地创建和销毁需要⼀定的开销。

  • 线程没有任务队列的任务管理功能:当任务数远远⼤于线程可以承载的数量之后,不能友好地进⾏任务拒绝。

2.线程池的定义

线程池(ThreadPool)是⼀种基于池化思想管理和使⽤线程的机制。

它是将多个线程预先存储在⼀个“池⼦”内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从“池⼦”内取出相应的线程执⾏对应的任务即可。

池化思想在计算机的应⽤也⽐较⼴泛:

  • 内存池(Memory Pooling):预先申请内存,提升申请内存速度,减少内存碎⽚。

  • 连接池(Connection Pooling):预先申请数据库连接,提升申请连接的速度,降低系统的开销。

  • 实例池(Object Pooling):循环使⽤对象,减少资源在初始化和释放时的昂贵损耗。

3.线程池的优点

  1. 复用线程:避免线程重复创建和销毁的性能开销。
  2. 提⾼响应速度:任务到达时,⽆需等待线程创建即可⽴即执⾏。
  3. 控制线程数量:避免因线程创建过多而导致OOM(out of memory内存溢出)情况。
  4. 提供内存管理功能:可实现任务缓存和任务拒绝。
  5. 提供更多功能:比如定时任务,允许任务延期执⾏或定期执⾏。

同时阿⾥巴巴在其《Java开发⼿册》中也强制规定:线程资源必须通过线程池提供,不允许在应⽤中⾃⾏显式创建线程。

4.线程池的创建/使用(2类7种)

4.1.通过Executors(执行器)自动创建(6种)

Executors.newFixedThreadPool:创建⼀个固定⼤⼩的线程池,可控制并发的线程数,超出的线程会在队列中等待。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 创建一个固定大小的线程池*/
public class ThreadPoolDemo1 {public static void main(String[] args) {//1.创建了一个包含5个线程的线程池ExecutorService threadPool = Executors.newFixedThreadPool(5);//2.使用submit线程池执行任务一for (int i = 0; i < 5; i++) {//给线程池添加任务threadPool.submit(new Runnable() { //匿名内部类@Overridepublic void run() {System.out.println("线程名称:" + Thread.currentThread().getName());}});}//2.使用execute线程池执行任务二for (int i = 0; i < 10; i++) {//给线程池添加任务threadPool.execute(new Runnable() {@Overridepublic void run() {System.out.println("线程名称:" + Thread.currentThread().getName());}});}}
}

--->PS:submit VS execute

 

  • submit:既支持有返回值,也支持无返回值。(推荐使用)
  • execute:只支持无返回值。

--->PS:有返回值的线程池实现

import java.util.Random;
import java.util.concurrent.*;/*** 有返回值的线程池*/
public class ThreadPoolDemo2 {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService threadPool = Executors.newFixedThreadPool(5);Future<Integer> result = threadPool.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception{int num = new Random().nextInt(10);System.out.println("生成随机数:" + num);return num;}});System.out.println("得到线程池返回结果:" + result.get()); //会有阻塞,会等到拿到返回值之后再去执行后面的代码}
}

上面代码是使用默认的线程工厂。

--->PS:线程池中的线程工厂

作用:为线程池提供线程的创建。

提供的功能:

  1. 设置线程池中的线程的命名规则。
  2. 设置线程的优先级。
  3. 设置线程的分组。
  4. 设置线程的类型(用户线程、守护/后台线程)。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import static java.lang.Thread.MAX_PRIORITY;/***线程工厂示例演示*/
public class ThreadPoolDemo3 {public static void main(String[] args) {//创建线程工厂ThreadFactory factory = new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {//!!!一定要注意要把任务Runnable设置给新创建的线程Thread thread = new Thread(r);//设置线程的命名规则thread.setName("我的线程-" + r.hashCode());//设置线程的优先级thread.setPriority(MAX_PRIORITY);return thread;}};ExecutorService service = Executors.newFixedThreadPool(5,factory);for (int i = 0; i < 5; i++) {service.submit(() -> {//任务Thread thread = Thread.currentThread();System.out.println("线程池开始执行了:" + thread.getName() + ",线程优先级:" + thread.getPriority());});}}
}

线程池里的线程永远处于存活状态,不会自动停止,除非调用线程池终止执行方法。

Executors.newCachedThreadPool:创建⼀个可缓存的线程池,若线程数超过处理所需,缓存⼀段时间后会回收,若线程数量不够,则新建线程,线程数随任务量而定(前提CPU性能好)。

优点:更多任务数量产⽣相应的线程池。 当有突发的大量的任务时,建议使用此方式。

缺点:占⽤资源数量⽐较多。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 带缓存的线程池*/
public class ThreadPoolDemo4 {public static void main(String[] args) {//创建线程池ExecutorService service = Executors.newCachedThreadPool();for (int i = 0; i < 1000; i++) {//任务数量总共有1000个,最终执行结果 线程数量大概是300多个//i必须定义一个参数,才能去使用,必须是一个确定的参数int finalI = i;service.submit(() -> {System.out.println("i:" + finalI + "|线程名称" + Thread.currentThread().getName());});}}
}

若不关闭,会一直执行下去。

Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执⾏顺序。

--->PS:(常见面试题)newSingleThreadExecutor:创建单个线程数的线程池,那为何不直接使用线程?单线程线程池的意义?

  1. 复用线程。
  2. 单线程的线程池提供了任务队列和拒绝策略(当任务队列满了Integer.MAX_VALUE之后,新来的任务就会执行拒绝策略)。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo7 {public static void main(String[] args) {ExecutorService service = Executors.newSingleThreadExecutor();for (int i = 0; i < 10; i++) {int finalI = i;service.submit(new Runnable() {@Overridepublic void run() {System.out.println("任务:" + finalI + "线程名:" + Thread.currentThread().getName());}});}}
}

Executors.newScheduledThreadPool:创建⼀个可以执⾏延迟任务的线程池。

--->a.延迟执行一次

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** 创建执行定时任务的线程池*/
public class ThreadPoolDemo5 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务的时间:" + LocalDateTime.now());//执行一次的定时任务scheduleTest(service);}/*** 执行一次的定时任务* @param service*/private static void scheduleTest(ScheduledExecutorService service) {//执行定时任务(延迟3秒执行)。这个延迟任务只能执行一次,不能继续执行。//延迟执行一次定时任务service.schedule(new Runnable() {@Overridepublic void run() {System.out.println("执行了任务:" + LocalDateTime.now());//参数1:执行的任务}},3, TimeUnit.SECONDS);//参数2:延迟多久进行执行; 参数3:是参数2的时间单位描述}
}

--->b.固定频率执行scheduleAtFixedRate

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** 创建执行定时任务的线程池*/
public class ThreadPoolDemo5 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务的时间:" + LocalDateTime.now());//2s之后开始执行定时任务,定时任务每隔4s执行一次service.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println("执行任务:" + LocalDateTime.now());}},2,4, TimeUnit.SECONDS);}
}

--->c.固定频率执行scheduleWithFixedDelay

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** 创建执行定时任务的线程池*/
public class ThreadPoolDemo5 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务的时间:" + LocalDateTime.now());//2s之后开始执行定时任务,定时任务每隔4s执行一次service.scheduleWithFixedDelay(new Runnable() {@Overridepublic void run() {System.out.println("执行时间:" + LocalDateTime.now());}},2,4,TimeUnit.SECONDS);}
}

 --->PS:scheduleAtFixedRate VS scheduleWithFixedDelay

①scheduleAtFixedRate 是以上⼀次任务的开始时间,作为下次定时任务的参考时间的(参考时间+延迟任务=任务执⾏)。

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** 创建执行定时任务的线程池*/
public class ThreadPoolDemo5 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务的时间:" + LocalDateTime.now());//2s之后开始执行定时任务,定时任务每隔4s执行一次service.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println("执行任务:" + LocalDateTime.now());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}},2,4, TimeUnit.SECONDS);}
}

注意:

如果任务执⾏时间⼤于延迟任务设定的间隔时间,则会以任务执行时间为定时任务间隔周期来执行,即哪个值大就用哪个值作为定时任务间隔周期。

public class ThreadPoolDemo5 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务的时间:" + LocalDateTime.now());//2s之后开始执行定时任务,定时任务每隔3s执行一次service.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println("执行任务:" + LocalDateTime.now());try {Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();}}},2,3, TimeUnit.SECONDS);}
}

②scheduleWithFixedDelay 是以上⼀次任务的结束时间,作为下次定时任务的参考时间的。

public class ThreadPoolDemo5 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务的时间:" + LocalDateTime.now());//2s之后开始执行定时任务,定时任务每隔4s执行一次service.scheduleWithFixedDelay(new Runnable() {@Overridepublic void run() {System.out.println("执行时间:" + LocalDateTime.now());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}},2,4,TimeUnit.SECONDS);}
}

Executors.newSingleThreadScheduledExecutor:创建⼀个单线程的可以执行延迟任务的线程池。

newSingleThreadScheduledExecutor是newScheduledThreadPool的单线程版本。

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ThreadPoolDemo6 {public static void main(String[] args) {//创建执行定时任务的单线程线程池ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();System.out.println("添加任务的时间:" + LocalDateTime.now());service.schedule(new Runnable() {@Overridepublic void run() {System.out.println("执行任务:" + LocalDateTime.now());}},2, TimeUnit.SECONDS);}
}

Executors.newWorkStealingPool:根据当前服务器的CPU创建⼀个抢占式执⾏的线程池(任务执⾏顺序不确定)【JDK 1.8 添加】。

优点:智能、高效。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo8 {public static void main(String[] args) {//根据当前设备的配置自动生成线程池ExecutorService service = Executors.newWorkStealingPool();for (int i = 0; i < 100; i++) {service.submit(() -> {System.out.println("线程名:" + Thread.currentThread().getName());});}while(!service.isTerminated()){}}
}

4.2.通过ThreadPoolExecutor手动创建(1种)

⑦ThreadPoolExecutor:重点掌握,最原始方式,推荐使用。

--->Executors自动创建线程池返回的线程池对象的弊端如下:

  1. FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
  2. CachedThreadPool:允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

OOM代码演示:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 演示OOM*/
public class ThreadPoolDemo9 {static class OOMClass{//1M空间(M KB Byte)private byte[] bytes = new byte[1 * 1024 * 1024];}public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();Object[] objects = new Object[15];for (int i = 0; i < 15; i++) {int finalI = i;service.execute(() -> {try {Thread.sleep(finalI * 200);} catch (InterruptedException e) {e.printStackTrace();}OOMClass oomClass = new OOMClass();objects[finalI] = oomClass;System.out.println("执行第" + finalI + "次");});}}
}

关于参数设置

  • -XX:标准设置,所有 HotSpot 都⽀持的参数。
  • -X:⾮标准设置,特定的 HotSpot 才⽀持的参数。
  • -D:程序参数设置,-D参数=value,程序中使⽤:System.getProperty("获取")。
  • mx 是 memory max 的简称。

《阿里巴巴Java开发手册》中强制规定:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样让程序员更加明确线程池的运行规则,规避资源耗尽的风险。

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** 手动方式创建线程池*/
public class ThreadPoolDemo10 {public static void main(String[] args) {ThreadFactory factory = new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {Thread thread = new Thread(r);return thread;}};//手动方式创建线程池ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(100), factory, new ThreadPoolExecutor.DiscardPolicy());//设置任务for (int i = 0; i < 10; i++) {executor.submit(() -> {System.out.println("线程名称:" + Thread.currentThread().getName());});}//终止线程executor.shutdown();//当任务执行完直接就结束了}
}

--->a.ThreadPoolExecutor 参数说明(包含 7 个参数可供设置,最少需要设置5个参数)

  1. corePoolSize:核心线程数(正式员工的数量),可以⼤致理解为⻓期驻留的线程数⽬(除⾮设置了allowCoreThreadTimeOut)。对于不同的线程池,这个值可能会有很⼤区别,⽐如 newFixedThreadPool 会将其设置为 nThreads,⽽对于 newCachedThreadPool 则是为0

  2. maximumPoolSize:最大线程数(正式员工+临时员工的数量),就是线程不够时能够创建的最⼤线程数。同样进⾏对⽐,对于newFixedThreadPool,当然就是 nThreads,因为其要求是固定⼤⼩,⽽ newCachedThreadPool 则是 Integer.MAX_VALUE。

  3. keepAliveTime:空闲线程的保活时间(针对临时员工),如果线程的空闲时间超过这个值,那么将会被关闭。注意此值⽣效条件必须满⾜:空闲时间超过这个值,并且线程池中的线程数少于等于核⼼线程数 corePoolSize。当然核⼼线程默认是不会关闭的,除⾮设置了allowCoreThreadTimeOut(true)那么核⼼线程也可以被回收。

  4. TimeUnit:对参数3的时间单位描述

  5. BlockingQueue:任务/阻塞队列,⽤于存储线程池的待执⾏任务。必须要设置参数值;若不设置参数值,默认为Integer.MAX_VALUE,也会导致OOM问题。

  6. threadFactory:用于生成线程的线程工厂,可设置线程属性,⼀般我们可以⽤默认的就可以了。

  7. handler:拒绝策略管理器,处理极端问题。当线程池已经满了,但是又有新的任务提交的时候,该采取什么策略由这个来指定。有⼏种⽅式可供选择,像抛出异常、直接拒绝然后返回等,也可以⾃⼰实现相应的接⼝实现⾃⼰的逻辑。

--->b.线程池执行流程

--->c.线程池拒绝策略(4【JDK提供】+1【自定义】)

JDK提供的4种:

①AbortPolicy(默认的拒绝策略):提示异常,拒绝执行。

②DiscardPolicy:忽略最新的任务。

③DiscardOldestPolicy:忽略旧任务(任务队列中的第一个任务)。

④CallerRunsPolicy:使用调用线程池的线程来执行任务~叫救援。

自定义的1种:

5.线程池状态(5种)

RUNNING:

线程池创建之后的初始状态,这是最正常的状态:接受新的任务,处理等待队列中的任务。

②SHUTDOWN:

线程池不再接受新的任务提交,但是会继续处理等待队列中的任务,将其执行结束。

STOP:

线程池不接受新的任务提交,不再处理等待队列中的任务,中断正在执⾏任务的线程。

TIDYING:

该状态下所有的任务都销毁了,workCount 为 0。会执⾏钩⼦⽅法 terminated()。

TERMINATED:

terminated() ⽅法结束后,线程池的状态就会变成这个。

a.各个状态的转换过程

  • RUNNING -> SHUTDOWN:当调⽤了 shutdown() 后,会发⽣这个状态转换,这也是最重要的;
  • (RUNNING or SHUTDOWN) -> STOP:当调⽤ shutdownNow() 后,会发⽣这个状态转换;
  • SHUTDOWN -> TIDYING:当任务队列和线程池都清空后,会由 SHUTDOWN 转换为 TIDYING;  
  • STOP -> TIDYING:当任务队列清空后,发⽣这个转换;
  • TIDYING -> TERMINATED:当 terminated() ⽅法结束后。

b.shutdown VS shutdownNow

  • shutdown 执⾏时线程池终⽌接收新任务,并且会将任务队列中的任务处理完;
  • shutdownNow 执⾏时线程池终⽌接收新任务,并且会终⽌执⾏任务队列中的任务。

6.究竟选用哪种线程池?

阿⾥巴巴《Java开发⼿册》给的答案:推荐使⽤ThreadPoolExecutor 的⽅式进⾏线程池的创建,因为这种创建⽅式更可控,并且更加明确了线程池的运⾏规则,可以规避⼀些未知的⻛险。

相关文章:

JavaWeb14-线程池

目录 1.传统线程的缺点 2.线程池的定义 3.线程池的优点 4.线程池的创建/使用&#xff08;2类7种&#xff09; 4.1.通过Executors&#xff08;执行器&#xff09;自动创建&#xff08;6种&#xff09; ①Executors.newFixedThreadPool&#xff1a;创建⼀个固定⼤⼩的线程池…...

[qiankun+nuxt]子应用请求本地文件报错404

前言 目前公司的前端架构是qiankunnuxt做的微前端项目 问题说明 在子应用中&#xff0c;前端需要模拟一些数据&#xff0c;方便后期演示调整而不需要重新打包 所以将一些数据存储到了本地的json文件中&#xff0c;但是获取时报了404的错误&#xff0c;找不到该文件。 页面报错…...

【Qt网络编程】实现TCP协议通信

文章目录概要&#xff1a;本期主要讲解QT中对于TCP协议通信的实现。一、TCP协议二、Qt中TCP协议处理1.QTcpSocket2.QTcpServer三、Qt实现TCP通信1.客户端2.服务器端结尾概要&#xff1a;本期主要讲解QT中对于TCP协议通信的实现。 一、TCP协议 传输控制协议&#xff08;TCP&am…...

Webpack打包———处理样式资源

基本使用 本质上&#xff0c;webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时&#xff0c;它会在内部从一个或多个入口点构建一个 依赖图(dependency graph)&#xff0c;然后将你项目中所需的每一个模块组合成一个或多个 bundles&a…...

VP记录:Codeforces Round 857 (Div. 2) A~D

传送门:CF A题 Likes: 这道题的题意很变态,十分的难懂,简直就是一坨shit,这场比赛最后被骂是有原因的 简单来说就是对于一个项目,每一个人都能对此加一或者减一,最后问你这个项目每一时刻最大和最小是多少.题目中只说明了只能点赞后才能取消,并没有解释存在取消操作必存在点…...

Docker常用项目实战演练

docker镜像源的修改 linux环境下编辑 /etc/docker/daemon.json vi /etc/docker/daemon.json #如添加如下网易镜像源 { "registry-mirrors": ["http://hub-mirror.c.163.com"] }docker run命令详细解释 日常工作中用的比较多的是docker run命令&#xff…...

Linux进程间通信-FIFO命名管道

Linux进程间通信-FIFO命名管道 1、概述 管道因为没有名称&#xff0c;所以只用于进程间的亲缘通信。为了克服这一缺点&#xff0c;提出了命名管道(FIFO)&#xff0c;又称命名管道、FIFO文件。 FIFO不同于无名管道&#xff0c;它提供与之关联的路径名&#xff0c;该路径名以FIF…...

【Kafka】记录一次基于connect-mirror-maker做的Kafka集群迁移完整过程

文章目录背景环境工具选型实操MM1MM2以MM2集群运行以Standalone模式运行验证附录MM2配置表其他背景 一个测试环境的kafka集群&#xff0c;Topic有360&#xff0c;Partition有2000&#xff0c;部署在虚拟机上&#xff0c;由于多方面原因&#xff0c;要求迁移至k8s容器内&#x…...

实现VOC数据集与COCO数据集格式转换

实现VOC数据集与COCO数据集格式转换2、将voc数据集的xml转化为coco数据集的json格式2、COCO格式的json文件转化为VOC格式的xml文件3、将 txt 文件转换为 Pascal VOC 的 XML 格式<annotation><folder>文件夹目录</folder><filename>图片名.jpg</file…...

常用的密码算法有哪些?

我们将密码算法分为两大类。 对称密码&#xff08;密钥密码&#xff09;——算法只有一个密钥。如果多个参与者都知道该密钥&#xff0c;该密钥 也称为共享密钥。非对称密码&#xff08;公钥密码&#xff09;——参与者对密钥的可见性是非对称的。例如&#xff0c;一些参与者仅…...

SNS (Simple Notification Service)简介

SNS (Simple Notification Service) 是一种完全托管的发布/订阅消息收发和移动通知服务&#xff0c;用于协调向订阅终端节点和客户端的消息分发。 和SQS (Simple Queue Service)一样&#xff0c;SNS也可以轻松分离和扩展微服务&#xff0c;分布式系统和无服务应用程序&#xf…...

JVM初步理解浅析

一、JVM的位置 JVM的位置 JVM在操作系统的上一层&#xff0c;是运行在操作系统上的。JRE是运行环境&#xff0c;而JVM是包含在JRE中 二、JVM体系结构 垃圾回收主要在方法区和堆&#xff0c;所以”JVM调优“大部分也是发生在方法区和堆中 可以说调优就是发生在堆中&#xf…...

【巨人的肩膀】MySQL面试总结(一)

&#x1f4aa; 目录&#x1f4aa;1、什么是ER图2、数据库范式了解吗3、超键、候选键、主键、外键分别是什么&#xff1f;4、为什么不推荐使用外键与级联5、什么是存储过程6、drop、delete与truncate区别7、数据库设计通常分为那几步8、什么是关系型数据库9、什么是SQL10、MySQL…...

【数据结构之树】——什么是树,树的特点,树的相关概念和表示方法以及在实际的应用。

文章目录一、1.树是什么&#xff1f;2.树的特点二、树的相关概念三、树的表示方法1.常规方法表示树2.使用左孩子右兄弟表示法3. 使用顺序表来存储父亲节点的下标三、树在实际的应用总结一、1.树是什么&#xff1f; 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n&…...

JavaScript语法

文章目录一、JavaScript是什么&#xff1f;JavaScript引入方式二、基础语法书写语法输出语句变量数据类型运算符流程控制语句数组函数JS变量作用域对象一、JavaScript是什么&#xff1f; JavaScript&#xff1a;是一门跨平台的脚本语言&#xff0c;用来控制网页行为&#xff0…...

【BIOS/UEFI】HII 基本框架及概述

HII&#xff08;Human Interface Infrastructure &#xff09;定义了一套管理用户输入的基础框架。HII数据库主要提供用户安装、卸载以及使用各种字符串、字体和图片等资源的接口。 HID Devices 是用户输入设备&#xff0c;如键盘、串口和网络&#xff1b;Display Devices 是输…...

sprintf(...)溢出边界导致程序崩溃的问题

文章目录小结问题及解决参考小结 使用sprintf(...)进行格式化是一种标准的做法&#xff0c;但是这样做是有一个极大的风险&#xff0c;由于sprintf(...)不进行边界检查&#xff0c;这样会有写操作溢出边界的风险&#xff0c;并导致程序崩溃。本文进行了简单写操作溢出边界的测…...

公式推导+dfs简版

写在前面的话&#xff1a;心可以冷&#xff0c;但手不能停 第一题&#xff1a;C. Flexible String 题目大意&#xff1a;给一个aaa字符串和bbb字符串和数字kkk&#xff0c;首先设置一个计数器cntcntcnt,其中可以对aaa字符串做以下操作&#xff1a;替换aaa中的一个字母xxx&#…...

论文笔记 | 标准误聚类问题

关于标准误的选择&#xff0c;如是否选择稳健性标准误、是否采取聚类标准误。之前一直是困惑的&#xff0c;惯用的做法是类似主题的文献做法。所以这一次&#xff0c;借计量经济学课程之故&#xff0c;较深入学习了标准误的选择问题。 在开始之前推荐一个知乎博主。他阅读了很…...

银行管理系统--课后程序(Python程序开发案例教程-黑马程序员编著-第7章-课后作业)

实例1&#xff1a;银行管理系统 从早期的钱庄到现如今的银行&#xff0c;金融行业在不断地变革&#xff1b;随着科技的发展、计算机的普及&#xff0c;计算机技术在金融行业得到了广泛的应用。银行管理系统是一个集开户、查询、取款、存款、转账、锁定、解锁、退出等一系列的功…...

【18】组合逻辑 - VL18 实现3-8译码器①

VL18 实现3-8译码器① 1 题目 【这题我的思路非常绝境】奈斯 !! 看真值表的思路:Yi所在列【0仅一个其余全1】,故【以0为对象求解】 观察发现:E3 E2_n E1_n = 100 时 是 译码的使能信号 ; 并且E3 E2_n E1_n为其他值时,都不使能译码 然后就很简单,没有仿真就成功了 2 代…...

2020蓝桥杯真题最长递增 C语言/C++

题目描述 在数列a_1 ,a_2,⋯,a_n 中&#xff0c;如果a_i <a_i1 <a_i2<⋯<a_j&#xff0c;则称 a_i至 a_j为一段递增序列&#xff0c;长度为 j−i1。 定一个数列&#xff0c;请问数列中最长的递增序列有多长。 输入描述 输入的第一行包含一个整数 n。 第二行包含…...

华为OD机试题 - 寻找连续区间(JavaScript)| 机考必刷

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:寻找连续区间题目输入输出示例一输入输出说明示例二输入输出Cod…...

一次疲惫的调试--累了及时透气

原创 射频清茶 深山小老虎 2023-03-11 14:32发表于广东 收录于合集 #射频调试3个 #网分4个 #Wi-Fi 2个 进来透透气 道不尽红尘舍恋 诉不完人间恩怨 世世代代都是缘 喝着相同的水 留着相同的血 这条路漫漫又长远 红花当然配绿叶 这一辈子谁来陪 渺渺茫茫来又回 往日情景再…...

综合练习7 摄氏度转华氏温度(“\t“的使用,循环语句)

综合练习7 摄氏度转华氏温度 使用do…while循环&#xff0c;在控制台输入摄氏温度与华氏温度的对照表。 对照表从摄氏温度-30℃到50℃&#xff0c;每行间隔10℃&#xff0c;运行如下&#xff1a; 摄氏温度&#xff1a;-30℃ 华氏温度&#xff1a;-22.0℉ 摄氏温度&#xff1a;…...

AWS数据库总结

RDS – 联机事务处理OLTP&#xff08;Online Transaction Processing&#xff09;&#xff0c;包括&#xff1a; SQL ServerOracleMySQL ServerPostgreSQLAuroraMariaDB非关系数据库DynamoDB数据仓库RedShift – 联机分析处理OLAP&#xff08;Online Analytics Processing&…...

2个步骤就能批量给视频添加滚动字幕

现在很多小伙伴在剪辑视频的时候都会给自己的视频添加适配的字幕&#xff0c;但是有很多的视频想要添加一样的滚动字幕时&#xff0c;有一个能批量添加剪辑的工具非常重要&#xff0c;今天小编就给大家分享一个可以批量剪辑大量视频的工具&#xff0c;下面一起看看具体的操作步…...

PHP 的运行方式有哪些?

PHP本质上的运行方式可以分为两种&#xff1a; 基于命令行的基于PHP-FPM的 但实际上&#xff0c;PHP能做的事很多&#xff0c;很多场景下&#xff0c;不同的运行方式能让开发更方便&#xff0c;减轻各种工作。 测试开发 PHP内置了一个HTTP 的server。这意味着&#xff0c;很…...

Web学习3_JavaScript

1.1 JS的调用方式与执行顺序 使用方式 HTML页面中的任意位置加上<script type"module"></script>标签即可。 常见使用方式有以下几种&#xff1a; 直接在<script type"module"></script>标签内写JS代码。script type"modu…...

「MySQL基础」不可重复读和幻读的区别

「MySQL基础」不可重复读和幻读的区别 文章参考&#xff1a; 在数据库中不可重复读和幻读到底应该怎么分&#xff1f; 作者&#xff1a;暖猫Suki、普通熊猫 文章目录「MySQL基础」不可重复读和幻读的区别一、概述二、小结一、概述 正好在琢磨这个问题&#xff0c;也被搞得头昏…...

CorelDRAW2023最新版新增功能200多个新模板

CorelDRAW是一款平面矢量绘图排版软件&#xff0c;CorelDRAW运用涵盖企业VI设计&#xff0c;广告设计&#xff0c;包装设计&#xff0c;画册设计&#xff0c;海报、招贴设计&#xff0c;UI界面设计&#xff0c;网页设计&#xff0c;书籍装帧设计&#xff0c;插画设计&#xff0…...

springboot自定义日志以及行号正确展示

在开发springboot项目时&#xff0c;我们可能需要自定义日志实现。需要对slf4j的日志实现进行一次外层包装 这个很简单&#xff0c;按照org.slf4j.Logger方式定义一个类Logger类MyLogger。 让后实现MyLoggerImpl&#xff1a; public class MyLoggerImpl implements CoreLogge…...

【GAOPS055】verilog 乘法、除法和取余

乘法硬件原理 结论 可以将乘法A x B转为A的移位相加。 利用乘2n就是左移n位的特性乘2^n就是左移n位的特性乘2n就是左移n位的特性&#xff0c;将数拆分为2n2^n2n表示 思路1 原始列竖式计算方法ref例2.9 思路2 B总是可以拆分为&#xff1a;B(an2nan−12n−1...a121a020)B(…...

TCP UPD详解

文章目录TCP UDP协议1. 概述2. 端口号 复用 分用3. TCP3.1 TCP首部格式3.2 建立连接-三次握手3.3 释放连接-四次挥手3.4 TCP流量控制3.5 TCP拥塞控制3.6 TCP可靠传输的实现3.7 TCP超时重传4. UDP5.TCP与UDP的区别TCP UDP协议 1. 概述 TCP、UDP协议是TCP/IP体系结构传输层中的…...

金三银四、金九银十 面试宝典 MySQL面试题 超级无敌全的面试题汇总(超万字的面试题,让你的MySQL无可挑剔)

MySQL数据库 - 面试宝典 又到了 金三银四、金九银十 的时候了&#xff0c;是时候收藏一波面试题了&#xff0c;面试题可以不学&#xff0c;但不能没有&#xff01;&#x1f941;&#x1f941;&#x1f941; 一个合格的 计算机打工人 &#xff0c;收藏夹里必须有一份 MySQL 八…...

【Java】初识Java

Java和C语言有许多类似之处&#xff0c;这里就只挑不一样的点来说&#xff0c;所以会比较杂乱哈~ 目录 1.数据类型 2.输入与输出 2.1三种输出 2.2输入 2.3循环输入输出 //猜数字小游戏 //打印乘法口诀表 3.方法 //交换两个数&#xff08;数组的应用&#xff09; //模…...

JVM相关知识

JVM类加载过程类什么时候被加载什么情况下会发生栈内存溢出JVM内存模型常量池回收方法区垃圾回收流程圾收集算法分代收集理论标记-清除算法标记-复制算法标记-整理算法类加载过程 加载–验证–准备–解析–初始化–使用–卸载 ​ 加载&#xff1a;通过全类名获取类的二进制流…...

【LeetCode】剑指 Offer(21)

目录 题目&#xff1a;剑指 Offer 39. 数组中出现次数超过一半的数字 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;剑指 Offer 40. 最小的k个数 -…...

线性求解器Ax=b的验证

文章目录前言Matrix MarketMatlab IORead dataWrite data测试C IORead and write dataDownload MatrixIO 代码下载参考网址前言 一般情况集成了一个线性求解器&#xff08;Axb&#xff09;&#xff0c;我们需要验证其性能和精度&#xff0c;这时需要大量数据来做验证&#xff…...

java 事件处理机制 观察者模式

事件处理机制有三个要素事件、事件源、事件监听与java的对应关系如下事件事件源事件监听javaclassjava.util.EventObjectjava.util.EventObject 的 source 属性interfacejava.util.EventListener观察者模式又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09;模式&…...

使用 HTML5 轻松验证表单插件

下载:https://download.csdn.net/download/mo3408/87559594 效果图: 当您通过表单从人们那里收集信息时,必须应用某种验证。如果不这样做,可能会导致客户流失、数据库中的垃圾数据甚至网站的安全漏洞。从历史上看,构建表单验证一直很痛苦。在服务器端,全栈框架会为您处理…...

【Error: ImagePullBackOff】Kubernetes中Nginx服务启动失败排查流程

❌pod节点启动失败&#xff0c;nginx服务无法正常访问&#xff0c;服务状态显示为ImagePullBackOff。 [rootm1 ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-f89759699-cgjgp 0/1 ImagePullBackOff 0 103…...

九龙证券|直逼1.5万亿!A股融资余额创年内新高,青睐这些行业和个股

2023年以来&#xff0c;A股商场震动重复&#xff0c;商场走势整体先扬后抑&#xff0c;各路资金看法纷歧&#xff0c;但数据显现&#xff0c;融资客在此期间整体持续净买入&#xff0c;未受到商场动摇的明显冲击&#xff0c;融资余额日前已迫临1.5万亿元&#xff0c;创出年内新…...

【JavaScript】36_正则表达式

正则表达式 正则表达式 正则表达式用来定义一个规则通过这个规则计算机可以检查一个字符串是否符合规则 或者将字符串中符合规则的内容提取出来 正则表达式也是JS中的一个对象&#xff0c; 所以要使用正则表达式&#xff0c;需要先创建正则表达式的对象 new RegExp() 可以…...

参考 | 辨别真假笔记本三星内存条 (ddr4)

参考 | 辨别真假笔记本三星内存条 (ddr4) 文章目录参考 | 辨别真假笔记本三星内存条 (ddr4)1. 三星内存条标签纸上编码的含义2. 三星内存颗粒上编码的含义3. 辨别内容参考1. 三星内存条标签纸上编码的含义 内存条贴张上面有两串值得注意的编码, 其中编码的具体意义参考三星官方…...

JavaScript Math(算数)对象

Math&#xff08;算数&#xff09;对象的作用是&#xff1a;执行常见的算数任务。在线实例round()如何使用 round()。random()如何使用 random() 来返回 0 到 1 之间的随机数。max()如何使用 max() 来返回两个给定的数中的较大的数。&#xff08;在 ECMASCript v3 之前&#xf…...

MyBatis里面用了多少种设计模式?

在MyBatis的两万多行的框架源码中&#xff0c;使用了大量的设计模式对工程架构中的复杂场景进行解耦&#xff0c;这些设计模式的巧妙使用是整个框架的精华。经过整理&#xff0c;大概有以下设计模式&#xff0c;如图1所示。图101类型&#xff1a;创建型模式▊ 工厂模式SqlSessi…...

第三十二周精华分享(2023.02.27-2023.03.06)

本帖是知识星球各类问答以及文章精华沉淀区&#xff0c;而知识星球相关资源沉淀则在置顶帖的「资源沉淀」中。 学计算机的都应该知道有个局部性原理&#xff0c;其实局部性原理在很多场合都适用&#xff0c;比如80%的圈友的痛点或者疑惑其实都集中在一些固定的方面或者问题上&…...

数学建模资料整理

数学建模中有三类团队&#xff1a; 第一类&#xff1a;拿到题目&#xff0c;讨论&#xff0c;然后建模手开始建模&#xff0c;编程手开始处理数据&#xff0c;写作手开始写作。 第二类&#xff1a;拿到题目&#xff0c;团内大佬&#xff0c;开始建模&#xff0c;然后编程&#…...

设计模式---抽象工厂模式

目录 1 介绍 2 优缺点 3 实现 1 介绍 抽象工厂模式(Abstract Factory Pattern) 是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 在抽象工厂模式中&#xff0c;接口是负…...