定时器原理剖析

定时器的基础是jdk中的工具类ScheduledThreadPoolExecutor,想要了解springboot定时器的原理,先得了解ScheduledThreadPoolExecutor的原理。

该类中有三个主要的方法:

  1. schedule(...)
  2. scheduleWithFixedDelay(...)
  3. scheduleAtFixedRate(...)

我们先简单回顾下这三个方法。

schedule方法

schedule方法的作用是提供一个延时执行的任务,该任务只会执行一次。该方法的三个参数如下

 
  1. schedule(Runnable command, long delay, TimeUnit unit)

  2. 复制代码

command为需要执行的任务,delay和unit组合起来使用,表示延时的时间。

 
  1. public ScheduledFuture<?> schedule(Runnable command,

  2. long delay,

  3. TimeUnit unit) {

  4. //校验参数

  5. if (command == null || unit == null)

  6. throw new NullPointerException();

  7. //任务转换

  8. RunnableScheduledFuture<?> t = decorateTask(command,

  9. new ScheduledFutureTask<Void>(command, null,

  10. triggerTime(delay, unit)));

  11. //添加任务到延时队列

  12. delayedExecute(t);

  13. return t;

  14. }

  15. 复制代码

首先看一下任务转换的逻辑:

 
  1. //将延时的时间加上现在的时间,转化成真正执行任务的时间

  2. private long triggerTime(long delay, TimeUnit unit) {

  3. return triggerTime(unit.toNanos((delay < 0) ? 0 : delay));

  4. }

  5. //将任务转化为ScheduledFutureTask对象

  6. ScheduledFutureTask(Runnable r, V result, long ns) {

  7. super(r, result);

  8. this.time = ns;

  9. //period为0表示只执行一次

  10. this.period = 0;

  11. this.sequenceNumber = sequencer.getAndIncrement();

  12. }

  13. 复制代码

接下来就是添加进任务队列:

 
  1. private void delayedExecute(RunnableScheduledFuture<?> task) {

  2. //检查任务状态

  3. if (isShutdown())

  4. reject(task);

  5. else {

  6. //添加进队列

  7. super.getQueue().add(task);

  8. //在执行之前,再次检查任务状态

  9. if (isShutdown() &&

  10. !canRunInCurrentRunState(task.isPeriodic()) &&

  11. remove(task))

  12. task.cancel(false);

  13. else

  14. //检查是否有线程在处理任务,如果工作线程数少于核心线程数,会新建worker。

  15. ensurePrestart();

  16. }

  17. }

  18. 复制代码

添加的逻辑看完了,现在看一下加入队列后是如何执行的:

 
  1. //worker线程会调用刚刚封装好的ScheduledFutureTask对象的run方法

  2. public void run() {

  3. //判断period是否是0

  4. boolean periodic = isPeriodic();

  5. if (!canRunInCurrentRunState(periodic))

  6. cancel(false);

  7. else if (!periodic)

  8. //在schedule方法中period是0,进入父类的run方法,run方法中

  9. //会调用我们传入的任务

  10. ScheduledFutureTask.super.run();

  11. else if (ScheduledFutureTask.super.runAndReset()) {

  12. setNextRunTime();

  13. reExecutePeriodic(outerTask);

  14. }

  15. }

  16. 复制代码

schedule方法的执行逻辑大致如上,schedule方法只执行一次。

scheduleWithFixedDelay方法

该方法的作用是在任务执行完成后,经过固定延时时间再次运行。

 
  1. public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,

  2. long initialDelay,

  3. long delay,

  4. TimeUnit unit) {

  5. //校验参数

  6. if (command == null || unit == null)

  7. throw new NullPointerException();

  8. if (delay <= 0)

  9. throw new IllegalArgumentException();

  10. //将任务转化为ScheduledFutureTask对象,注意这个地方period不是0了!

  11. ScheduledFutureTask<Void> sft =

  12. new ScheduledFutureTask<Void>(command,

  13. null,

  14. triggerTime(initialDelay, unit),

  15. unit.toNanos(-delay));

  16. //将outerTask设置为自己

  17. RunnableScheduledFuture<Void> t = decorateTask(command, sft);

  18. sft.outerTask = t;

  19. //添加进延时队列

  20. delayedExecute(t);

  21. return t;

  22. }

  23. 复制代码

和schedule方法稍有不同,一个是period不在是0,而是小于0,还有就是将outerTask设置为自己。

添加进任务队列的逻辑都是一样的,所以直接看执行逻辑:

 
  1. public void run() {

  2. //这个地方periodic是true了

  3. boolean periodic = isPeriodic();

  4. if (!canRunInCurrentRunState(periodic))

  5. cancel(false);

  6. else if (!periodic)

  7. ScheduledFutureTask.super.run();

  8. //所以会进入下面这个逻辑

  9. else if (ScheduledFutureTask.super.runAndReset()) {

  10. //设置下一次任务时间

  11. setNextRunTime();

  12. //将自己再次添加进队列

  13. reExecutePeriodic(outerTask);

  14. }

  15. }

  16. //period是小于0的,注意这个地方大于0和小于0逻辑上的区别

  17. private void setNextRunTime() {

  18. long p = period;

  19. if (p > 0)

  20. //大于0的话,是用上次执行的时间,加上延时时间算出下次执行的时间

  21. time += p;

  22. else

  23. //小于0的话,是用当前时间,加上延时时间,算出下次执行时间

  24. time = triggerTime(-p);

  25. }

  26. 复制代码

scheduleAtFixedRate方法

这个方法和上一个方法几乎一样,唯一的区别就是他的period是大于0的,所以延时时间按照大于0来计算。


springboot中定时器的原理

了解完ScheduledThreadPoolExecutor的基础原理后,我们来看一下springboot中定时任务的调度。springboot定时任务调度的基础是ScheduledAnnotationBeanPostProcessor类,查看继承体系发现该类实现了BeanPostProcessor接口,所以进入该类的postProcessAfterInitialization方法。

 
  1. public Object postProcessAfterInitialization(Object bean, String beanName) {

  2. if (bean instanceof AopInfrastructureBean || bean instanceof TaskScheduler ||

  3. bean instanceof ScheduledExecutorService) {

  4. // Ignore AOP infrastructure such as scoped proxies.

  5. return bean;

  6. }

  7. Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);

  8. if (!this.nonAnnotatedClasses.contains(targetClass)) {

  9. //查找被Scheduled注解标注的类

  10. Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass,

  11. (MethodIntrospector.MetadataLookup<Set<Scheduled>>) method -> {

  12. Set<Scheduled> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(

  13. method, Scheduled.class, Schedules.class);

  14. return (!scheduledMethods.isEmpty() ? scheduledMethods : null);

  15. });

  16. if (annotatedMethods.isEmpty()) {

  17. this.nonAnnotatedClasses.add(targetClass);

  18. if (logger.isTraceEnabled()) {

  19. logger.trace("No @Scheduled annotations found on bean class: " + targetClass);

  20. }

  21. }

  22. else {

  23. // Non-empty set of methods

  24. //如果被Scheduled注解标注,就执行processScheduled方法。

  25. annotatedMethods.forEach((method, scheduledMethods) ->

  26. scheduledMethods.forEach(scheduled -> processScheduled(scheduled, method, bean)));

  27. if (logger.isTraceEnabled()) {

  28. logger.trace(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName +

  29. "': " + annotatedMethods);

  30. }

  31. }

  32. }

  33. return bean;

  34. }

  35. //以cron模式来解析一下processScheduled方法

  36. protected void processScheduled(Scheduled scheduled, Method method, Object bean) {

  37. try {

  38. Runnable runnable = createRunnable(bean, method);

  39. boolean processedSchedule = false;

  40. ...

  41. // 解析注解里的属性

  42. String cron = scheduled.cron();

  43. if (StringUtils.hasText(cron)) {

  44. String zone = scheduled.zone();

  45. if (this.embeddedValueResolver != null) {

  46. cron = this.embeddedValueResolver.resolveStringValue(cron);

  47. zone = this.embeddedValueResolver.resolveStringValue(zone);

  48. }

  49. if (StringUtils.hasLength(cron)) {

  50. Assert.isTrue(initialDelay == -1, "'initialDelay' not supported for cron triggers");

  51. processedSchedule = true;

  52. if (!Scheduled.CRON_DISABLED.equals(cron)) {

  53. TimeZone timeZone;

  54. if (StringUtils.hasText(zone)) {

  55. timeZone = StringUtils.parseTimeZoneString(zone);

  56. }

  57. else {

  58. timeZone = TimeZone.getDefault();

  59. }

  60. //将封装好的任务存储起来

  61. tasks.add(this.registrar.scheduleCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone))));

  62. }

  63. }

  64. }

  65. ...

  66. // Finally register the scheduled tasks

  67. synchronized (this.scheduledTasks) {

  68. Set<ScheduledTask> regTasks = this.scheduledTasks.computeIfAbsent(bean, key -> new LinkedHashSet<>(4));

  69. //根据bean分类,将每个bean的定时任务存进scheduledTasks

  70. regTasks.addAll(tasks);

  71. }

  72. }

  73. ...

  74. }

  75. public ScheduledTask scheduleCronTask(CronTask task) {

  76. ScheduledTask scheduledTask = this.unresolvedTasks.remove(task);

  77. boolean newTask = false;

  78. if (scheduledTask == null) {

  79. //根据task,新建一个ScheduledTask

  80. scheduledTask = new ScheduledTask(task);

  81. newTask = true;

  82. }

  83. if (this.taskScheduler != null) {

  84. scheduledTask.future = this.taskScheduler.schedule(task.getRunnable(), task.getTrigger());

  85. }

  86. else {

  87. //根据定时任务种类的区别存储task

  88. addCronTask(task);

  89. this.unresolvedTasks.put(task, scheduledTask);

  90. }

  91. return (newTask ? scheduledTask : null);

  92. }

  93. 复制代码

在postProcessAfterInitialization方法中,spring主要就是解析注解,并将根据注解生成相应的延时任务。那么现在解析好了,也存储好了,执行的地方在哪里呢?在一次查看该类的继承体系,发现该类还实现了ApplicationListener接口,所以进入onApplicationEvent方法。

 
  1. public void onApplicationEvent(ContextRefreshedEvent event) {

  2. if (event.getApplicationContext() == this.applicationContext) {

  3. finishRegistration();

  4. }

  5. }

  6. private void finishRegistration() {

  7. ...

  8. //上面一大段都是寻找taskScheduler类的,如果没有设置的话这边是找不到的

  9. this.registrar.afterPropertiesSet();

  10. }

  11. public void afterPropertiesSet() {

  12. scheduleTasks();

  13. }

  14. protected void scheduleTasks() {

  15. //没有自定义配置就使用默认配置

  16. if (this.taskScheduler == null) {

  17. //默认的执行器只有一个线程使用的时候要注意一下

  18. this.localExecutor = Executors.newSingleThreadScheduledExecutor();

  19. this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);

  20. }

  21. if (this.triggerTasks != null) {

  22. for (TriggerTask task : this.triggerTasks) {

  23. addScheduledTask(scheduleTriggerTask(task));

  24. }

  25. }

  26. if (this.cronTasks != null) {

  27. for (CronTask task : this.cronTasks) {

  28. addScheduledTask(scheduleCronTask(task));

  29. }

  30. }

  31. if (this.fixedRateTasks != null) {

  32. for (IntervalTask task : this.fixedRateTasks) {

  33. addScheduledTask(scheduleFixedRateTask(task));

  34. }

  35. }

  36. if (this.fixedDelayTasks != null) {

  37. for (IntervalTask task : this.fixedDelayTasks) {

  38. addScheduledTask(scheduleFixedDelayTask(task));

  39. }

  40. }

  41. }

  42. 复制代码

在该方法中,清晰的看到了定时任务调用的过程triggerTasks好像不是通过注解进来的,这个先不管。我们可以看一下另外三个的执行。

cron执行逻辑

 
  1. public ScheduledTask scheduleCronTask(CronTask task) {

  2. ScheduledTask scheduledTask = this.unresolvedTasks.remove(task);

  3. ...

  4. //这个地方taskScheduler已经有默认值了

  5. if (this.taskScheduler != null) {

  6. scheduledTask.future = this.taskScheduler.schedule(task.getRunnable(), task.getTrigger());

  7. }

  8. ...

  9. return (newTask ? scheduledTask : null);

  10. }

  11. public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {

  12. try {

  13. ...

  14. else {

  15. ...

  16. //新建了一个ReschedulingRunnable对象,调用schedule方法。

  17. return new ReschedulingRunnable(task, trigger, this.scheduledExecutor, errorHandler).schedule();

  18. }

  19. }

  20. ...

  21. }

  22. //新建一个ReschedulingRunnable对象,这个对象也实现了runnable接口

  23. public ReschedulingRunnable(

  24. Runnable delegate, Trigger trigger, ScheduledExecutorService executor, ErrorHandler errorHandler) {

  25. super(delegate, errorHandler);

  26. this.trigger = trigger;

  27. this.executor = executor;

  28. }

  29. public ScheduledFuture<?> schedule() {

  30. synchronized (this.triggerContextMonitor) {

  31. this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);

  32. if (this.scheduledExecutionTime == null) {

  33. return null;

  34. }

  35. //计算下次执行时间

  36. long initialDelay = this.scheduledExecutionTime.getTime() - System.currentTimeMillis();

  37. //将自己传入执行器,也就是调用自己的run方法

  38. this.currentFuture = this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);

  39. return this;

  40. }

  41. }

  42. public void run() {

  43. Date actualExecutionTime = new Date();

  44. //执行我们定义的定时任务

  45. super.run();

  46. Date completionTime = new Date();

  47. synchronized (this.triggerContextMonitor) {

  48. Assert.state(this.scheduledExecutionTime != null, "No scheduled execution");

  49. //更新时间

  50. this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);

  51. if (!obtainCurrentFuture().isCancelled()) {

  52. //在次调用schedule方法

  53. schedule();

  54. }

  55. }

  56. }

  57. 复制代码

在上面我们分析执行器逻辑的时候,知道执行器的schedule方法只会执行一次,所以springboot在这个地方使用互相调用的方法,来达到定时循环的目的。所以这个方法中,关键的就是时间的更新。

 
  1. public Date nextExecutionTime(TriggerContext triggerContext) {

  2. //获取上一次任务完成时间

  3. Date date = triggerContext.lastCompletionTime();

  4. if (date != null) {

  5. //获取上一次任务执行的时间

  6. Date scheduled = triggerContext.lastScheduledExecutionTime();

  7. //比较两次时间,使用后者生成新的执行时间

  8. if (scheduled != null && date.before(scheduled)) {

  9. date = scheduled;

  10. }

  11. }

  12. else {

  13. //初始化的时候直接使用当前时间

  14. date = new Date();

  15. }

  16. return this.sequenceGenerator.next(date);

  17. }

  18. 复制代码

cron模式每次根据上次执行时间和上次完成时间更后面的生成新的时间,结合肥朝的文章应该可以理解这种模型。不过这个地方我也不太明白什么情况下完成时间会在执行时间的前面。反正就是根据最新的时间生成新的时间就是。

剩下的两个执行逻辑

 
  1. public ScheduledTask scheduleFixedRateTask(IntervalTask task) {

  2. FixedRateTask taskToUse = (task instanceof FixedRateTask ? (FixedRateTask) task :

  3. new FixedRateTask(task.getRunnable(), task.getInterval(), task.getInitialDelay()));

  4. return scheduleFixedRateTask(taskToUse);

  5. }

  6. public ScheduledTask scheduleFixedRateTask(FixedRateTask task) {

  7. ...

  8. scheduledTask.future =

  9. this.taskScheduler.scheduleAtFixedRate(task.getRunnable(), task.getInterval());

  10. ...

  11. return (newTask ? scheduledTask : null);

  12. }

  13. public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {

  14. try {

  15. return this.scheduledExecutor.scheduleAtFixedRate(decorateTask(task, true), 0, period, TimeUnit.MILLISECONDS);

  16. }

  17. catch (RejectedExecutionException ex) {

  18. throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);

  19. }

  20. }

  21. 复制代码

另外两个模式就是执行ScheduledThreadPoolExecutor对应的方法了,关键还是时间的逻辑,时间的生成逻辑上面已经给出来了,就是根据period大于0还是小于0来生成的。

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

相关文章

  1. PAT (Basic Level) Practice 1013 数素数

    测试点4&#xff1a;测试素数的范围从2到105000&#xff01;&#xff01;&#xff01; #include<bits/stdc.h> using namespace std; int a[100000]; int c1; void getPrime(){int flag0;int i,j;for(i2;i<105000;i){flag1;for(j2;j<sqrt(i);j){if(i%j0){flag0;br…...

    2024/4/24 19:44:07
  2. SVN下如何回退(revert)到某一版本

    回退&#xff08;revert&#xff09;到某一版本马克- to-win&#xff1a;马克 java社区&#xff1a;防盗版实名手机尾号&#xff1a; 73203 马克-to-win&#xff1a;在公司里&#xff0c;经常有这种情况&#xff0c;比如刚才wanzi已经提交自己满意的版本12&#xff0c;而mark是…...

    2024/4/27 1:22:14
  3. python - 单链表1

    Q&#xff1a;为什么要写链表&#xff1f;只用list不行么&#xff1f; A&#xff1a;链表(linked list)这一数据结构具体有哪些实际应用&#xff1f; - 知乎 目前我能看懂的部分&#xff1a; 插入和删除的效率高&#xff0c;不用遍历。只要你读源码&#xff0c;你就会发现 has…...

    2024/4/28 3:24:14
  4. deep Q learning 里的 模型的ground-truth 的初步理解

    由前文 https://blog.csdn.net/guotong1988/article/details/120774481 bellman equation 的释义是 time1-action 加 time0-reward 作为 time0-action 的 ground-truth 具体代码&#xff1a;...

    2024/4/28 6:58:34
  5. (大数字计算)一个9位数的8次方的结果再对一个9位数取模(取余数)运算

    &#xff08;大数字计算&#xff09;一个9位数的8次方的结果再对一个9位数取模&#xff08;取余数&#xff09;运算 前几天写过一篇文章关于这个主题的&#xff1a; java超越int的存在----BigInteger 可是&#xff0c;无助的我发现&#xff0c;那种BIG类型的数据其实很不好用&…...

    2024/4/26 16:23:30
  6. 在数组中查找一个数据

    一&#xff1a;折半查找&#xff08;数组中数据必须连续&#xff09; 算法&#xff1a;例如1 3 5 6 7 9 中查找7&#xff0c;将19除以2为5而7比大&#xff0c;则在69除以2 为7。 代码&#xff1a; #include<stdio.h> #include<math.h>int main() {int arr[10];i…...

    2024/4/15 5:50:53
  7. Python之数据处理与可视化

    数据基本处理&#xff1a;Numpy和Pandas 1.csv文件处理 数据导入&#xff1a;pd.read_csv() dfpd.read_csv(“文件名”,sep“分隔符”,header0,index_colNone,encoding“字符编码”) 数据导出&#xff1a;pd.to_csv() df.to_csv(“文件名”,indexFalse,headerTure) 2.txt文…...

    2024/4/28 4:08:14
  8. “21天好习惯”第一期-14

    1. 2....

    2024/4/27 21:30:13
  9. spingBean装配和注入1103

    1.简单来说&#xff0c;原来我new一个对象&#xff0c;必须要有这个类&#xff08;否则编译器都会出错&#xff09;&#xff0c;现在也需要&#xff0c;但是我只需要查询你的名字存不存在在创建对象和初始化。 控制反转&#xff08;IOC:Inversion of Control&#xff09;&…...

    2024/4/27 21:32:57
  10. HAUT AUTO 算法入门

    1.枚举 //主要是督促自己学习 //就直接枚举&#xff0c;一个一个试&#xff0c;不废话直接for #include<iostream> #include <algorithm> #include <iomanip> using namespace std;int main() {int a,b,c,d,N;cin >> N;for (a 2; a < N; a)for (b …...

    2024/4/28 8:28:01
  11. 非科班的java程序员该如何补充计算机基础知识,需要看哪些书?

    这里是修真院后端小课堂,本篇分析的主题是【非科班的java程序员该如何补充计算机基础知识,需要看哪些书?】java比较特殊,毕竟后端扛霸子,想要认真学好java,必须有好的计算机基础,可是为什么需要基础呢?把这个问题弄明白,要学哪些基础知识就清楚多了。第一个问题,10个…...

    2024/4/27 21:44:02
  12. 车载串行器MAX96717F的使用

    随着ADAS的发展&#xff0c;车载传感器的使用随着技术的发展已经呈现几何式的增长&#xff0c;特别是车载摄像头与车载雷达的装载量&#xff0c;其中特别是车载摄像头&#xff0c;现在以特斯拉为首的造车新势力在视觉传感上都已经单车装载量达到8~14PCS&#xff0c;其中前视摄像…...

    2024/4/28 0:36:48
  13. python循环往列表list里存放字典dict无效,结果都为最后一个字典dict

    项目场景&#xff1a; python字典dict循环往列表list里存放 问题描述&#xff1a; 循环改变字典dict中的值再存放入列表list中&#xff0c;最后列表里的字典无效&#xff0c;都为最后一个字典。 简易化的错误代码&#xff1a;&#xff08;以等线为分割每次循环&#xff09; d…...

    2024/4/24 17:16:56
  14. dajngo与vue前后端分离

    dajngo与vue前后端分离一、说明二、数据流程三、后端配置四、前端一、说明 软件安装 后端&#xff1a;python、django、djangorestframework、django-cors-hearders前端&#xff1a;nod.js 、vue/cli、axios dajngo与vue前后端分离 二、数据流程 三、后端配置 相关软件库安…...

    2024/4/28 4:35:35
  15. acwing算法基础 快速排序

    八分半时间带你了解快速排序&#xff08;思路讲解加代码展示&#xff09;_哔哩哔哩_bilibili 我看了好久没看懂&#xff0c;就去b站找资源&#xff0c;然后发现这个视频很容易懂 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; const int N 1e6 …...

    2024/4/28 4:05:04
  16. 内存的连续分配管理

    ...

    2024/4/20 16:36:56
  17. C语言刷题笔记11

    Problem 1 输出26个英文字母 描述&#xff1a; 编写一个程序&#xff0c;分别按正向和逆向输出小写字母。 输入说明&#xff1a; 无。 输出说明&#xff1a; 字母间以空格分隔&#xff0c;正向输出完换行&#xff0c;再逆向输出。 输入样例 无。 输出样例 无。 代…...

    2024/4/27 1:10:15
  18. Day 28数据库

    数据库 安装 参考教程即可 1 检测自己是否安装(安装就卸载) 2 Navicart安装 3 测试 数据库概述 在操作系统中使用文件进行数据存储,跨平台性能 要差一些,而数据库是可以解决数据跨平台问题的 数据库 : 望文知义 就是遵循一定数据格式的数据集合,可以认为是对文件系统的改进…...

    2024/4/28 15:49:51
  19. pytorch1.60 torch.nn在pycharm中无法自动智能提示

    问题描述 安装了pytorch最新版本1.6之后&#xff0c;在pycharm中编辑python代码时&#xff0c;输入torch.nn.看不到提示了&#xff0c;比如torch.nn.MSELoss()。而在1.4及以前的版本中&#xff0c;直接输入torch.nn.就会自动提示出很多torch.nn.modules中的API。 该问题的讨论在…...

    2024/4/28 5:09:28
  20. 使用nginx配置静态页面展示sphinx-doc

    文章目录安装nginx系统: Ubuntu目的: 使用sphinx-doc给实验室制作了一套找工作的经验说明, 但是生成的index尝试了使用Django挂载特别麻烦(需要修改静态文件js, css等的相对链接), 然后发现还可以有两种方式挂载到网络上面, 这里使用nginx挂载思路: 首先我有一个云服务器, 所以…...

    2024/4/28 13:55:00

最新文章

  1. QT +C++环境使用Python.h调用python函数时使用了matplotlib画图出现问题

    问题描述&#xff1a; 代码、函数没有任何问题就只有matplotlib部分有问题。 原因1&#xff1a; 使用了.show函数&#xff0c;QT中不可像python那样使用matplotlib进行交互&#xff0c;所以删除show改成存储在指定位置即可 import matplotlib matplotlib.use(Agg) # 使用非交…...

    2024/4/28 17:49:51
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. FastAPI Web框架教程 第1章 快速上手

    1.1 fastapi介绍 简介&#xff1a; FastAPI 是一个高性能&#xff0c;易于学习&#xff0c;高效编码&#xff0c;生产可用的Python Web异步框架 FastAPI 适合来写API&#xff0c;使用 Python 3.6 并基于标准的 Python 类型提示 核心特性&#xff1a; 速度快&#xff1a;可…...

    2024/4/25 6:24:33
  4. CentOS 7查看磁盘空间

    CentOS如何查看硬盘大小&#xff1f; CentOS是一种基于Linux的操作系统&#xff0c;主要用于服务器端应用。在服务器管理中&#xff0c;硬盘大小是一个非常重要的指标&#xff0c;查看硬盘大小可以帮助系统管理员有效地管理硬盘空间和避免硬盘满了的情况。 方法一&#xff1a…...

    2024/4/24 14:59:47
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/28 13:52:11
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/28 3:28:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/26 23:05:52
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/28 13:51:37
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/28 15:57:13
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/28 1:22:35
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/25 18:39:14
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/26 23:04:58
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/26 19:46:12
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/27 11:43:08
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/27 8:32:30
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57